summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSuper Liu <supercjliu@google.com>2020-04-20 13:36:39 +0800
committerSuper Liu <supercjliu@google.com>2020-04-20 16:22:02 +0800
commit5e918dd46cd80ea96b49c4817a1c62ef272ea6a5 (patch)
treed1481e24e82cbff462390b148859c1c322880f1a
parent408003f18439ff07599b083cf64b2aefd698da10 (diff)
downloadsec_touch-5e918dd46cd80ea96b49c4817a1c62ef272ea6a5.tar.gz
sec_touch: continuously report heatmap data for first single touch
Bug: 154432814 Change-Id: I30779158b3021193a411296c53e5ca47a9b038a8 Signed-off-by: Super Liu <supercjliu@google.com>
-rw-r--r--sec_ts.c85
-rw-r--r--sec_ts.h25
-rw-r--r--sec_ts_fn.c1
3 files changed, 110 insertions, 1 deletions
diff --git a/sec_ts.c b/sec_ts.c
index e7c57c5..04899e8 100644
--- a/sec_ts.c
+++ b/sec_ts.c
@@ -1216,6 +1216,71 @@ static void sec_ts_reinit(struct sec_ts_data *ts)
#if defined(CONFIG_TOUCHSCREEN_HEATMAP) || \
defined(CONFIG_TOUCHSCREEN_HEATMAP_MODULE)
+/* Update a state machine used to toggle control of the touch IC's motion
+ * filter.
+ */
+static void update_motion_filter(struct sec_ts_data *ts)
+{
+ /* Motion filter timeout, in milliseconds */
+ const u32 mf_timeout_ms = 500;
+ u8 next_state;
+ /* Count the active touches */
+ u8 touches = hweight32(ts->tid_touch_state);
+
+ if (ts->use_default_mf)
+ return;
+
+ /* Determine the next filter state. The motion filter is enabled by
+ * default and it is disabled while a single finger is touching the
+ * screen. If another finger is touched down or if a timeout expires,
+ * the motion filter is reenabled and remains enabled until all fingers
+ * are lifted.
+ */
+ next_state = ts->mf_state;
+ switch (ts->mf_state) {
+ case SEC_TS_MF_FILTERED:
+ if (touches == 1) {
+ next_state = SEC_TS_MF_UNFILTERED;
+ ts->mf_downtime = ktime_get();
+ }
+ break;
+ case SEC_TS_MF_UNFILTERED:
+ if (touches == 0) {
+ next_state = SEC_TS_MF_FILTERED;
+ } else if (touches > 1 ||
+ ktime_after(ktime_get(),
+ ktime_add_ms(ts->mf_downtime,
+ mf_timeout_ms))) {
+ next_state = SEC_TS_MF_FILTERED_LOCKED;
+ }
+ break;
+ case SEC_TS_MF_FILTERED_LOCKED:
+ if (touches == 0)
+ next_state = SEC_TS_MF_FILTERED;
+ break;
+ }
+
+ /* Send command to update filter state */
+ if ((next_state == SEC_TS_MF_UNFILTERED) !=
+ (ts->mf_state == SEC_TS_MF_UNFILTERED)) {
+ int ret;
+ u8 para;
+
+ pr_debug("%s: setting motion filter = %s.\n", __func__,
+ (next_state == SEC_TS_MF_UNFILTERED) ?
+ "false" : "true");
+ para = (next_state == SEC_TS_MF_UNFILTERED) ? 0x01 : 0x00;
+ ret = ts->sec_ts_write(ts, SEC_TS_CMD_SET_CONT_REPORT,
+ &para, 1);
+ if (ret < 0) {
+ input_err(true, &ts->client->dev,
+ "%s: write reg %#x para %#x failed, returned %i\n",
+ __func__, SEC_TS_CMD_SET_CONT_REPORT, para, ret);
+ }
+ }
+ ts->mf_state = next_state;
+}
+
static bool read_heatmap_raw(struct v4l2_heatmap *v4l2)
{
struct sec_ts_data *ts = container_of(v4l2, struct sec_ts_data, v4l2);
@@ -1537,13 +1602,15 @@ static void sec_ts_handle_coord_event(struct sec_ts_data *ts,
if (ts->touch_count > 0)
ts->touch_count--;
- if (ts->touch_count == 0) {
+ if (ts->touch_count == 0 ||
+ ts->tid_touch_state == 0) {
input_report_key(ts->input_dev,
BTN_TOUCH, 0);
input_report_key(ts->input_dev,
BTN_TOOL_FINGER, 0);
ts->check_multi = 0;
}
+ __clear_bit(t_id, &ts->tid_touch_state);
} else if (ts->coord[t_id].action ==
SEC_TS_COORDINATE_ACTION_PRESS) {
@@ -1562,6 +1629,7 @@ static void sec_ts_handle_coord_event(struct sec_ts_data *ts,
(unsigned int)ts->coord[t_id].z;
input_mt_slot(ts->input_dev, t_id);
+ __set_bit(t_id, &ts->tid_touch_state);
input_mt_report_slot_state(ts->input_dev,
MT_TOOL_FINGER, 1);
input_report_key(ts->input_dev, BTN_TOUCH, 1);
@@ -1621,6 +1689,7 @@ static void sec_ts_handle_coord_event(struct sec_ts_data *ts,
input_mt_slot(ts->input_dev, t_id);
input_mt_report_slot_state(ts->input_dev,
MT_TOOL_FINGER, 1);
+ __set_bit(t_id, &ts->tid_touch_state);
input_report_key(ts->input_dev, BTN_TOUCH, 1);
input_report_key(ts->input_dev,
BTN_TOOL_FINGER, 1);
@@ -2083,6 +2152,12 @@ static irqreturn_t sec_ts_irq_thread(int irq, void *ptr)
mutex_unlock(&ts->eventlock);
+#if defined(CONFIG_TOUCHSCREEN_HEATMAP) || \
+ defined(CONFIG_TOUCHSCREEN_HEATMAP_MODULE)
+ /* Disable the firmware motion filter during single touch */
+ update_motion_filter(ts);
+#endif
+
pm_qos_update_request(&ts->pm_qos_req, PM_QOS_DEFAULT_VALUE);
sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_IRQ, false);
@@ -3188,6 +3263,8 @@ static int sec_ts_probe(struct spi_device *client)
}
ts->touch_count = 0;
+ ts->tid_touch_state = 0;
+
ts->sec_ts_write = sec_ts_write;
ts->sec_ts_read = sec_ts_read;
ts->sec_ts_read_heap = sec_ts_read_heap;
@@ -3267,6 +3344,9 @@ static int sec_ts_probe(struct spi_device *client)
pm_qos_add_request(&ts->pm_qos_req, PM_QOS_CPU_DMA_LATENCY,
PM_QOS_DEFAULT_VALUE);
+ /* init motion filter mode */
+ ts->use_default_mf = 0;
+ ts->mf_state = SEC_TS_MF_FILTERED;
#if defined(CONFIG_TOUCHSCREEN_HEATMAP) || \
defined(CONFIG_TOUCHSCREEN_HEATMAP_MODULE)
/*
@@ -3471,6 +3551,8 @@ void sec_ts_unlocked_release_all_finger(struct sec_ts_data *ts)
ts->touchkey_glove_mode_status = false;
ts->touch_count = 0;
ts->check_multi = 0;
+ ts->tid_touch_state = 0;
+
#ifdef KEY_SIDE_GESTURE
if (ts->plat_data->support_sidegesture) {
input_report_key(ts->input_dev, KEY_SIDE_GESTURE, 0);
@@ -3534,6 +3616,7 @@ void sec_ts_locked_release_all_finger(struct sec_ts_data *ts)
ts->touchkey_glove_mode_status = false;
ts->touch_count = 0;
ts->check_multi = 0;
+ ts->tid_touch_state = 0;
#ifdef KEY_SIDE_GESTURE
if (ts->plat_data->support_sidegesture) {
diff --git a/sec_ts.h b/sec_ts.h
index e3f0d3b..db90f48 100644
--- a/sec_ts.h
+++ b/sec_ts.h
@@ -633,6 +633,18 @@ enum {
HEATMAP_FULL = 2
};
+/* Motion filter finite state machine (FSM) states
+ * SEC_TS_MF_FILTERED - default coordinate filtering
+ * SEC_TS_MF_UNFILTERED - unfiltered single-touch coordinates
+ * SEC_TS_MF_FILTERED_LOCKED - filtered coordinates. Locked until touch is
+ * lifted.
+ */
+enum motion_filter_state_t {
+ SEC_TS_MF_FILTERED = 0,
+ SEC_TS_MF_UNFILTERED = 1,
+ SEC_TS_MF_FILTERED_LOCKED = 2
+};
+
#if defined(CONFIG_TOUCHSCREEN_HEATMAP) || \
defined(CONFIG_TOUCHSCREEN_HEATMAP_MODULE)
/* Local heatmap */
@@ -842,6 +854,15 @@ struct sec_ts_data {
struct pm_qos_request pm_qos_req;
+ /* Stop changing motion filter and keep fw design */
+ u8 use_default_mf;
+ /* Motion filter finite state machine (FSM) state */
+ enum motion_filter_state_t mf_state;
+ /* Time of initial single-finger touch down. This timestamp is used to
+ * compute the duration a single finger is touched before it is lifted.
+ */
+ ktime_t mf_downtime;
+
u8 frame_type;
#if defined(CONFIG_TOUCHSCREEN_HEATMAP) || \
defined(CONFIG_TOUCHSCREEN_HEATMAP_MODULE)
@@ -949,6 +970,10 @@ struct sec_ts_data {
};
};
+ /* slot id active state(bit mask) for all touch types
+ **/
+ unsigned long tid_touch_state;
+
#ifdef CONFIG_TOUCHSCREEN_TBN
struct tbn_context *tbn;
#endif
diff --git a/sec_ts_fn.c b/sec_ts_fn.c
index 95ba891..52ea692 100644
--- a/sec_ts_fn.c
+++ b/sec_ts_fn.c
@@ -439,6 +439,7 @@ static void set_continuous_report_enable(void *device_data)
goto err_out;
}
+ ts->use_default_mf = para;
scnprintf(buff, sizeof(buff), "%s", "OK");
sec->cmd_state = SEC_CMD_STATUS_OK;
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));