diff options
author | davidycchen <davidycchen@google.com> | 2022-02-25 16:12:12 +0800 |
---|---|---|
committer | davidycchen <davidycchen@google.com> | 2022-03-07 16:28:12 +0800 |
commit | ba43ce7e908a9f7f8c234d8cf4a0aa4d4a4f87fa (patch) | |
tree | 8ddd32eae1cf1d69c015eac728ac54abf89b4a87 | |
parent | c5e2ea3daf0732f625ab00711168d53e05cf426d (diff) | |
download | synaptics_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.c | 94 | ||||
-rw-r--r-- | syna_tcm2_platform.h | 2 | ||||
-rw-r--r-- | syna_tcm2_platform_spi.c | 9 | ||||
-rw-r--r-- | tcm/synaptics_touchcom_core_dev.h | 14 | ||||
-rw-r--r-- | tcm/synaptics_touchcom_func_base.c | 1 |
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; } |