summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordavidycchen <davidycchen@google.com>2022-02-25 16:12:12 +0800
committerdavidycchen <davidycchen@google.com>2022-03-07 16:28:12 +0800
commitba43ce7e908a9f7f8c234d8cf4a0aa4d4a4f87fa (patch)
tree8ddd32eae1cf1d69c015eac728ac54abf89b4a87
parentc5e2ea3daf0732f625ab00711168d53e05cf426d (diff)
downloadsynaptics_touch-ba43ce7e908a9f7f8c234d8cf4a0aa4d4a4f87fa.tar.gz
synaptics: support finger leaves event for UDFPS
Bug: 220992096 Test: LHBM is off right after finger leaves. Signed-off-by: davidycchen <davidycchen@google.com> Change-Id: Ibc4fda47f8c3faca57b03b8a675e271c8051baa9
-rw-r--r--syna_tcm2.c94
-rw-r--r--syna_tcm2_platform.h2
-rw-r--r--syna_tcm2_platform_spi.c9
-rw-r--r--tcm/synaptics_touchcom_core_dev.h14
-rw-r--r--tcm/synaptics_touchcom_func_base.c1
5 files changed, 120 insertions, 0 deletions
diff --git a/syna_tcm2.c b/syna_tcm2.c
index 07b558c..2ca7ce5 100644
--- a/syna_tcm2.c
+++ b/syna_tcm2.c
@@ -1752,6 +1752,97 @@ static int syna_pinctrl_configure(struct syna_tcm *tcm, bool enable)
}
/**
+ * Report a finger down event on the long press gesture area then immediately
+ * report a cancel event(MT_TOOL_PALM).
+ */
+static void syna_report_cancel_event(struct syna_tcm *tcm)
+{
+ LOGI("Report cancel event for UDFPS");
+
+ syna_pal_mutex_lock(&tcm->tp_event_mutex);
+
+ /* Finger down on UDFPS area. */
+ input_mt_slot(tcm->input_dev, 0);
+ input_report_key(tcm->input_dev, BTN_TOUCH, 1);
+ input_mt_report_slot_state(tcm->input_dev, MT_TOOL_FINGER, 1);
+ input_report_abs(tcm->input_dev, ABS_MT_POSITION_X, tcm->hw_if->udfps_x);
+ input_report_abs(tcm->input_dev, ABS_MT_POSITION_Y, tcm->hw_if->udfps_y);
+ input_report_abs(tcm->input_dev, ABS_MT_TOUCH_MAJOR, 200);
+ input_report_abs(tcm->input_dev, ABS_MT_TOUCH_MINOR, 200);
+#ifndef SKIP_PRESSURE
+ input_report_abs(tcm->input_dev, ABS_MT_PRESSURE, 1);
+#endif
+ input_report_abs(tcm->input_dev, ABS_MT_ORIENTATION, 0);
+ input_sync(tcm->input_dev);
+
+ /* Report MT_TOOL_PALM for canceling the touch event. */
+ input_mt_slot(tcm->input_dev, 0);
+ input_report_key(tcm->input_dev, BTN_TOUCH, 1);
+ input_mt_report_slot_state(tcm->input_dev, MT_TOOL_PALM, 1);
+ input_sync(tcm->input_dev);
+
+ /* Release touches. */
+ input_mt_slot(tcm->input_dev, 0);
+ input_report_abs(tcm->input_dev, ABS_MT_PRESSURE, 0);
+ input_mt_report_slot_state(tcm->input_dev, MT_TOOL_FINGER, 0);
+ input_report_abs(tcm->input_dev, ABS_MT_TRACKING_ID, -1);
+ input_report_key(tcm->input_dev, BTN_TOUCH, 0);
+ input_sync(tcm->input_dev);
+
+ syna_pal_mutex_unlock(&tcm->tp_event_mutex);
+}
+
+static void syna_check_finger_status(struct syna_tcm *tcm)
+{
+ int retval = 0;
+ unsigned char code = 0;
+ u16 touch_mode, x, y, major, minor;
+ struct syna_hw_attn_data *attn = &tcm->hw_if->bdata_attn;
+ ktime_t timeout = ktime_add_ms(ktime_get(), 500);
+ LOGI("Check finger status");
+
+ while (ktime_get() < timeout) {
+ /* Clear the FIFO if there is pending data. */
+ if (gpio_get_value(attn->irq_gpio) == attn->irq_on_state) {
+ retval = tcm->tcm_dev->read_message(tcm->tcm_dev, &code);
+ continue;
+ }
+
+ retval = syna_tcm_get_dynamic_config(tcm->tcm_dev, DC_TOUCH_SCAN_MODE,
+ &touch_mode, RESP_IN_POLLING);
+ if (retval < 0)
+ continue;
+
+ if (touch_mode != SCAN_LPWG_IDLE && touch_mode != SCAN_LPWG_ACTIVE)
+ return;
+
+ LOGI("Poll finger events.");
+ while (ktime_get() < timeout) {
+ msleep(30);
+ syna_tcm_get_event_data(tcm->tcm_dev,
+ &code,
+ &tcm->event_data);
+ if (code == REPORT_TOUCH) {
+ x = syna_pal_le2_to_uint(&tcm->event_data.buf[1]);
+ y = syna_pal_le2_to_uint(&tcm->event_data.buf[3]);
+ major = tcm->event_data.buf[4];
+ minor = tcm->event_data.buf[5];
+ /* Touch reports coordinates and major/minor 0
+ * when the finger leaves.
+ */
+ if (x==0 && y==0 && major==0 && minor==0) {
+ syna_report_cancel_event(tcm);
+ return;
+ }
+ } else if (code == STATUS_INVALID) {
+ syna_report_cancel_event(tcm);
+ return;
+ }
+ }
+ }
+}
+
+/**
* syna_dev_resume()
*
* Resume from the suspend state.
@@ -1786,6 +1877,9 @@ static int syna_dev_resume(struct device *dev)
syna_pinctrl_configure(tcm, true);
+ if (hw_if->udfps_x != 0 && hw_if->udfps_y != 0)
+ syna_check_finger_status(tcm);
+
#ifdef RESET_ON_RESUME
LOGI("Do reset on resume\n");
diff --git a/syna_tcm2_platform.h b/syna_tcm2_platform.h
index 566387b..16c607d 100644
--- a/syna_tcm2_platform.h
+++ b/syna_tcm2_platform.h
@@ -150,6 +150,8 @@ struct syna_hw_interface {
#if IS_ENABLED(CONFIG_TOUCHSCREEN_OFFLOAD)
u32 offload_id;
#endif
+ int udfps_x;
+ int udfps_y;
/* Operation to do power on/off, if supported
*
diff --git a/syna_tcm2_platform_spi.c b/syna_tcm2_platform_spi.c
index 56fb5ad..683d6e4 100644
--- a/syna_tcm2_platform_spi.c
+++ b/syna_tcm2_platform_spi.c
@@ -446,6 +446,7 @@ static int syna_spi_parse_dt(struct syna_hw_interface *hw_if,
int retval;
int index;
u32 value;
+ u32 coords[2];
struct property *prop;
struct device_node *np = dev->of_node;
const char *name;
@@ -692,6 +693,14 @@ static int syna_spi_parse_dt(struct syna_hw_interface *hw_if,
}
#endif
+ if (of_property_read_u32_array(np, "synaptics,udfps-coords", coords, 2)) {
+ dev_err(dev, "synaptics,udfps-coords not found\n");
+ coords[0] = 0;
+ coords[1] = 0;
+ }
+ hw_if->udfps_x = coords[0];
+ hw_if->udfps_y = coords[1];
+
return 0;
}
#endif
diff --git a/tcm/synaptics_touchcom_core_dev.h b/tcm/synaptics_touchcom_core_dev.h
index 043d686..9acfdde 100644
--- a/tcm/synaptics_touchcom_core_dev.h
+++ b/tcm/synaptics_touchcom_core_dev.h
@@ -185,6 +185,19 @@ enum tcm_app_status {
};
/**
+ * @section: Touch Scan Mode Dynamic Configuration
+ *
+ * The current touch scan mode.
+ */
+enum tcm_scan_mode {
+ SCAN_NORMAL_IDLE = 0,
+ SCAN_NORMAL_ACTIVE,
+ SCAN_LPWG_IDLE,
+ SCAN_LPWG_ACTIVE,
+ SCAN_SLEEP,
+};
+
+/**
* @section: Field IDs in Dynamic Configuration
*
* The codes specify the generic dynamic configuration options.
@@ -209,6 +222,7 @@ enum dynamic_tcm_config_id {
DC_DISABLE_PROXIMITY = 0x10,
DC_HIGH_SENSITIVIRY_MODE = 0xCB,
DC_FORCE_DOZE_MODE = 0xF0,
+ DC_TOUCH_SCAN_MODE = 0xF2,
DC_ENABLE_PALM_REJECTION = 0xF3,
DC_CONTINUOUSLY_REPORT = 0xF5,
};
diff --git a/tcm/synaptics_touchcom_func_base.c b/tcm/synaptics_touchcom_func_base.c
index df9afb1..22b63e6 100644
--- a/tcm/synaptics_touchcom_func_base.c
+++ b/tcm/synaptics_touchcom_func_base.c
@@ -1281,6 +1281,7 @@ int syna_tcm_get_dynamic_config(struct tcm_dev *tcm_dev,
if (tcm_dev->resp_buf.data_length < 2) {
LOGE("Invalid resp data size, %d\n",
tcm_dev->resp_buf.data_length);
+ retval = _EINVAL;
goto exit;
}