summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSuper Liu <supercjliu@google.com>2022-03-31 11:38:45 +0800
committerSuper Liu <supercjliu@google.com>2022-04-08 15:16:16 +0800
commitb2b3e5fa44d416b72490f5850529d8e480e2f612 (patch)
treef679a25823431859855a6efa12834aade3033087
parent957e77c8bbdd91df08bc4539720ea9cbef4cf763 (diff)
downloadcommon-b2b3e5fa44d416b72490f5850529d8e480e2f612.tar.gz
touch/common: GTI support continuous reporting.
Bug: 201610482 Signed-off-by: Super Liu <supercjliu@google.com> Change-Id: Ic25eb25155d381835be4d26e6efc54d6509a59f3
-rw-r--r--goog_touch_interface.c79
-rw-r--r--goog_touch_interface.h37
2 files changed, 109 insertions, 7 deletions
diff --git a/goog_touch_interface.c b/goog_touch_interface.c
index 0a87083..2f02314 100644
--- a/goog_touch_interface.c
+++ b/goog_touch_interface.c
@@ -12,6 +12,67 @@
#include "goog_touch_interface.h"
#include "../../../gs-google/drivers/soc/google/vh/kernel/systrace.h"
+void goog_update_motion_filter(struct goog_touch_interface *gti, unsigned long slot_bit)
+{
+ const u32 mf_timeout_ms = 500;
+ unsigned long touches = hweight_long(slot_bit);
+ u32 next_state = gti->mf_state;
+
+ switch (gti->mf_mode) {
+ case GTI_MF_MODE_AUTO_REPORT:
+ case GTI_MF_MODE_UNFILTER:
+ next_state = GTI_MF_STATE_UNFILTERED;
+ break;
+ case GTI_MF_MODE_FILTER:
+ next_state = GTI_MF_STATE_FILTERED;
+ break;
+ case GTI_MF_MODE_DYNAMIC:
+ default:
+ /*
+ * 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.
+ */
+ switch (next_state) {
+ case GTI_MF_STATE_FILTERED:
+ if (touches == 1) {
+ next_state = GTI_MF_STATE_UNFILTERED;
+ gti->mf_downtime = ktime_get();
+ }
+ break;
+ case GTI_MF_STATE_UNFILTERED:
+ if (touches == 0) {
+ next_state = GTI_MF_STATE_FILTERED;
+ } else if (touches > 1 ||
+ ktime_after(ktime_get(),
+ ktime_add_ms(gti->mf_downtime, mf_timeout_ms))) {
+ next_state = GTI_MF_STATE_FILTERED_LOCKED;
+ }
+ break;
+ case GTI_MF_STATE_FILTERED_LOCKED:
+ if (touches == 0)
+ next_state = GTI_MF_STATE_FILTERED;
+ break;
+ }
+ break;
+ }
+
+ /* Send command to setup continuous report. */
+ if ((next_state == GTI_MF_STATE_UNFILTERED) !=
+ (gti->mf_state == GTI_MF_STATE_UNFILTERED)) {
+ u32 enable = GTI_SUB_CMD_DISABLE;
+
+ if (next_state == GTI_MF_STATE_UNFILTERED)
+ enable = GTI_SUB_CMD_ENABLE;
+ gti->vendor_cb(gti->vendor_private_data,
+ GTI_CMD_SET_CONTINUOUS_REPORT, enable, NULL, NULL);
+ }
+
+ gti->mf_state = next_state;
+}
+
bool goog_v4l2_read_frame_cb(struct v4l2_heatmap *v4l2)
{
struct goog_touch_interface *gti = container_of(v4l2, struct goog_touch_interface, v4l2);
@@ -180,6 +241,7 @@ void goog_offload_input_report(void *handle,
bool touch_down = 0;
unsigned int tool_type = MT_TOOL_FINGER;
int i;
+ unsigned long active_slot_bit = 0;
ATRACE_BEGIN(__func__);
@@ -199,6 +261,7 @@ void goog_offload_input_report(void *handle,
tool_type = MT_TOOL_FINGER;
break;
}
+ __set_bit(i, &active_slot_bit);
input_mt_slot(gti->input_dev, i);
touch_down = 1;
input_report_key(gti->input_dev, BTN_TOUCH, touch_down);
@@ -214,6 +277,7 @@ void goog_offload_input_report(void *handle,
input_report_abs(gti->input_dev, ABS_MT_PRESSURE,
report->coords[i].pressure);
} else {
+ __clear_bit(i, &active_slot_bit);
input_mt_slot(gti->input_dev, i);
input_report_abs(gti->input_dev, ABS_MT_PRESSURE, 0);
input_mt_report_slot_state(gti->input_dev, MT_TOOL_FINGER, 0);
@@ -227,9 +291,7 @@ void goog_offload_input_report(void *handle,
if (touch_down)
goog_v4l2_read(gti, report->timestamp);
- /*
- * TODO(b/201610482): Enable/disable continuous reporting.
- */
+ goog_update_motion_filter(gti, active_slot_bit);
ATRACE_END();
}
@@ -399,7 +461,7 @@ int goog_input_process(struct goog_touch_interface *gti)
* Otherwise, heatmap will be handled for both offload and v4l2
* during goog_offload_populate_frame().
*/
- if (!gti->offload.offload_running) {
+ if (!gti->offload.offload_running && gti->v4l2_enable) {
int ret;
u8 *buffer = NULL;
u32 size = 0;
@@ -410,6 +472,7 @@ int goog_input_process(struct goog_touch_interface *gti)
if (ret == 0 && buffer && size)
memcpy(gti->heatmap_buf, buffer, size);
goog_v4l2_read(gti, gti->timestamp);
+ goog_update_motion_filter(gti, gti->active_slot_bit);
}
gti->coord_changed = false;
@@ -486,10 +549,13 @@ void goog_input_mt_report_slot_state(
input_mt_report_slot_state(dev, tool_type, active);
if (tool_type == MT_TOOL_FINGER) {
- if (active)
+ if (active) {
gti->offload.coords[gti->slot].status = COORD_STATUS_FINGER;
- else
+ __set_bit(gti->slot, &gti->active_slot_bit);
+ } else {
gti->offload.coords[gti->slot].status = COORD_STATUS_INACTIVE;
+ __clear_bit(gti->slot, &gti->active_slot_bit);
+ }
}
}
EXPORT_SYMBOL(goog_input_mt_report_slot_state);
@@ -555,6 +621,7 @@ struct goog_touch_interface *goog_touch_interface_probe(
gti->dev = dev;
gti->input_dev = input_dev;
gti->vendor_cb = vendor_cb;
+ gti->mf_mode = GTI_MF_MODE_DEFAULT;
mutex_init(&gti->input_lock);
goog_offload_probe(gti);
}
diff --git a/goog_touch_interface.h b/goog_touch_interface.h
index ab0113f..16c32b7 100644
--- a/goog_touch_interface.h
+++ b/goog_touch_interface.h
@@ -23,7 +23,6 @@
#define KTIME_RELEASE_ALL (ktime_set(0, 0))
-
enum {
/*
* GTI_CMD_GET_SENSOR_DATA:
@@ -65,6 +64,34 @@ enum {
};
/**
+ * Motion filter finite state machine (FSM) state.
+ * GTI_MF_STATE_FILTERED: default coordinate filtering
+ * GTI_MF_STATE_UNFILTERED: coordinate unfiltering for single-touch.
+ * GTI_MF_STATE_FILTERED_LOCKED: filtered coordinates. Locked until
+ * touch is lifted or timeout.
+ */
+enum {
+ GTI_MF_STATE_FILTERED = 0,
+ GTI_MF_STATE_UNFILTERED,
+ GTI_MF_STATE_FILTERED_LOCKED,
+};
+
+/**
+ * Motion filter mode.
+ * GTI_MF_MODE_UNFILTER: enable unfilter by continuous reporting.
+ * GTI_MF_MODE_DYNAMIC: dynamic control for motion filter.
+ * GTI_MF_MODE_FILTER: only report touch if coord report changed.
+ * GTI_MF_MODE_AUTO: for development case.
+ */
+enum {
+ GTI_MF_MODE_UNFILTER = 0,
+ GTI_MF_MODE_DEFAULT,
+ GTI_MF_MODE_DYNAMIC = GTI_MF_MODE_DEFAULT,
+ GTI_MF_MODE_FILTER,
+ GTI_MF_MODE_AUTO_REPORT,
+};
+
+/**
* struct goog_touch_interfac - Google touch interface data for Pixel.
* @vendor_private_data: the private data pointer that used by touch vendor driver.
* @dev: pointer to struct device that used by touch vendor driver.
@@ -74,8 +101,11 @@ enum {
* @offload_frame: reserved frame that used by touch offload.
* @v4l2: struct that used by v4l2.
* @timestamp: irq timestamp from touch vendor driver.
+ * @mf_downtime: timestamp for motion filter control.
* @grip_setting: current grip setting.
* @palm_setting: current palm setting.
+ * @mf_mode: current motion filter mode.
+ * @mf_state: current motion filter state.
* @force_legacy_report: force to directly report input by kernel input API.
* @offload_enable: touch offload is enabled or not.
* @v4l2_enable: v4l2 is enabled or not.
@@ -84,6 +114,7 @@ enum {
* @heatmap_buf: heatmap buffer that used by v4l2.
* @heatmap_buf_size: heatmap buffer size that used by v4l2.
* @slot: slot id that current used by input report.
+ * @active_slot_bit: bitmap of active slot from legacy report.
* @vendor_cb: touch vendor driver function callback.
*/
@@ -96,9 +127,12 @@ struct goog_touch_interface {
struct touch_offload_frame *offload_frame;
struct v4l2_heatmap v4l2;
ktime_t timestamp;
+ ktime_t mf_downtime;
u32 grip_setting;
u32 palm_setting;
+ u32 mf_mode;
+ u32 mf_state;
bool force_legacy_report;
bool offload_enable;
@@ -111,6 +145,7 @@ struct goog_touch_interface {
u8 *heatmap_buf;
u32 heatmap_buf_size;
int slot;
+ unsigned long active_slot_bit;
int (*vendor_cb)(void *vendor_private_data,
u32 cmd, u32 sub_cmd, u8 **buffer, u32 *size);