summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordavidycchen <davidycchen@google.com>2022-03-09 15:30:23 +0800
committerdavidycchen <davidycchen@google.com>2022-05-06 10:37:20 +0800
commitdd8ac97f73c32cf96e2690a8b9efb911cccdee98 (patch)
tree36729654cff3295dd5dff582b6876faf5ccbd12f
parent55784dc0c6a43f8b0437848d80c60c77a31c45a2 (diff)
downloadsynaptics_touch-dd8ac97f73c32cf96e2690a8b9efb911cccdee98.tar.gz
synaptics: dynamic change the touch report rate
Dynamic change the touch report rate depending on the display refresh rate. Bug: 222217451 Test: Switch the display refresh rate while finger is sliding without issue. Signed-off-by: davidycchen <davidycchen@google.com> Change-Id: Ia258208d644ef2b0c94b3a2296e5d8253cae1774
-rw-r--r--syna_tcm2.c74
-rw-r--r--syna_tcm2.h6
-rw-r--r--syna_tcm2_platform.h1
-rw-r--r--syna_tcm2_platform_spi.c2
-rw-r--r--tcm/synaptics_touchcom_core_dev.h5
5 files changed, 84 insertions, 4 deletions
diff --git a/syna_tcm2.c b/syna_tcm2.c
index b0cef72..08be4a2 100644
--- a/syna_tcm2.c
+++ b/syna_tcm2.c
@@ -301,7 +301,15 @@ static void syna_dev_restore_feature_setting(struct syna_tcm *tcm)
DC_COMPRESSION_THRESHOLD,
tcm->hw_if->compression_threhsold,
RESP_IN_POLLING);
+
+ if (tcm->hw_if->dynamic_report_rate) {
+ syna_tcm_set_dynamic_config(tcm->tcm_dev,
+ DC_REPORT_RATE_SWITCH,
+ tcm->touch_report_rate_config,
+ RESP_IN_POLLING);
+ }
}
+
/* Update a state machine used to toggle control of the touch IC's motion
* filter.
*/
@@ -380,6 +388,28 @@ static void syna_motion_filter_work(struct work_struct *work)
RESP_IN_ATTN);
}
+static void syna_set_report_rate_work(struct work_struct *work)
+{
+ struct syna_tcm *tcm;
+ struct delayed_work *delayed_work;
+ delayed_work = container_of(work, struct delayed_work, work);
+ tcm = container_of(delayed_work, struct syna_tcm, set_report_rate_work);
+
+ if (tcm->touch_count != 0) {
+ queue_delayed_work(tcm->event_wq, &tcm->set_report_rate_work,
+ msecs_to_jiffies(10));
+ return;
+ }
+
+ tcm->touch_report_rate_config = tcm->next_report_rate_config;
+ syna_tcm_set_dynamic_config(tcm->tcm_dev,
+ DC_REPORT_RATE_SWITCH,
+ tcm->touch_report_rate_config,
+ RESP_IN_ATTN);
+ LOGI("Set touch report rate as %dHz",
+ (tcm->touch_report_rate_config == CONFIG_HIGH_REPORT_RATE) ? 240 : 120);
+}
+
#ifdef ENABLE_CUSTOM_TOUCH_ENTITY
/**
* syna_dev_parse_custom_touch_data_cb()
@@ -742,6 +772,7 @@ static void syna_dev_report_input_events(struct syna_tcm *tcm)
input_set_timestamp(input_dev, tcm->coords_timestamp);
input_sync(input_dev);
+ tcm->touch_count = touch_count;
syna_update_motion_filter(tcm, touch_count);
@@ -1043,6 +1074,8 @@ static void syna_offload_report(void *handle,
input_report_key(tcm->input_dev, BTN_TOOL_FINGER, touch_down);
input_sync(tcm->input_dev);
+ tcm->touch_count = touch_count;
+
syna_update_motion_filter(tcm, touch_count);
syna_pal_mutex_unlock(&tcm->tp_event_mutex);
@@ -2037,6 +2070,9 @@ static int syna_dev_suspend(struct device *dev)
LOGI("Prepare to suspend device\n");
+ if (tcm->hw_if->dynamic_report_rate)
+ cancel_delayed_work_sync(&tcm->set_report_rate_work);
+
reinit_completion(&tcm->bus_resumed);
/* clear all input events */
@@ -2319,7 +2355,7 @@ static void syna_panel_bridge_enable(struct drm_bridge *bridge)
struct syna_tcm *tcm =
container_of(bridge, struct syna_tcm, panel_bridge);
- pr_debug("%s\n", __func__);
+ LOGD("%s\n", __func__);
if (!tcm ->is_panel_lp_mode)
syna_set_bus_ref(tcm, SYNA_BUS_REF_SCREEN_ON, true);
}
@@ -2336,7 +2372,7 @@ static void syna_panel_bridge_disable(struct drm_bridge *bridge)
return;
}
- pr_debug("%s\n", __func__);
+ LOGD("%s\n", __func__);
syna_set_bus_ref(tcm, SYNA_BUS_REF_SCREEN_ON, false);
}
@@ -2347,10 +2383,10 @@ static void syna_panel_bridge_mode_set(struct drm_bridge *bridge,
struct syna_tcm *tcm =
container_of(bridge, struct syna_tcm, panel_bridge);
- pr_debug("%s\n", __func__);
+ LOGD("%s\n", __func__);
if (!tcm->connector || !tcm->connector->state) {
- pr_info("%s: Get bridge connector.\n", __func__);
+ LOGI("%s: Get bridge connector.\n", __func__);
tcm->connector = syna_get_bridge_connector(bridge);
}
@@ -2359,6 +2395,31 @@ static void syna_panel_bridge_mode_set(struct drm_bridge *bridge,
syna_set_bus_ref(tcm, SYNA_BUS_REF_SCREEN_ON, false);
else
syna_set_bus_ref(tcm, SYNA_BUS_REF_SCREEN_ON, true);
+
+ if (mode && tcm->hw_if->dynamic_report_rate) {
+ int vrefresh = drm_mode_vrefresh(mode);
+ LOGD("Display refresh rate %dHz", vrefresh);
+ if (vrefresh == 120 || vrefresh == 90)
+ tcm->next_report_rate_config = CONFIG_HIGH_REPORT_RATE;
+ else
+ tcm->next_report_rate_config = CONFIG_LOW_REPORT_RATE;
+
+ if (tcm->last_vrefresh_rate != vrefresh)
+ cancel_delayed_work_sync(&tcm->set_report_rate_work);
+
+ if (tcm->next_report_rate_config != tcm->touch_report_rate_config &&
+ tcm->pwr_state == PWR_ON && tcm->bus_refmask != 0) {
+ /*
+ * Queue the work immediately for increasing touch report rate
+ * to 240Hz and queue 2 seconds delay work for decreasing
+ * touch report rate.
+ */
+ queue_delayed_work(tcm->event_wq, &tcm->set_report_rate_work,
+ (tcm->next_report_rate_config == CONFIG_HIGH_REPORT_RATE) ?
+ 0 : msecs_to_jiffies(2 * MSEC_PER_SEC));
+ }
+ tcm->last_vrefresh_rate = vrefresh;
+ }
}
static const struct drm_bridge_funcs panel_bridge_funcs = {
@@ -2783,6 +2844,9 @@ static int syna_dev_probe(struct platform_device *pdev)
INIT_WORK(&tcm->motion_filter_work, syna_motion_filter_work);
+ tcm->touch_report_rate_config = CONFIG_HIGH_REPORT_RATE;
+ INIT_DELAYED_WORK(&tcm->set_report_rate_work, syna_set_report_rate_work);
+
#ifdef HAS_SYSFS_INTERFACE
/* create the device file and register to char device classes */
retval = syna_cdev_create_sysfs(tcm, pdev);
@@ -2904,6 +2968,8 @@ static int syna_dev_remove(struct platform_device *pdev)
cancel_work_sync(&tcm->suspend_work);
cancel_work_sync(&tcm->resume_work);
+ cancel_work_sync(&tcm->motion_filter_work);
+ cancel_delayed_work_sync(&tcm->set_report_rate_work);
#if IS_ENABLED(CONFIG_TOUCHSCREEN_TBN)
if (tcm->tbn_register_mask)
diff --git a/syna_tcm2.h b/syna_tcm2.h
index b37a1a9..89668fc 100644
--- a/syna_tcm2.h
+++ b/syna_tcm2.h
@@ -480,6 +480,12 @@ struct syna_tcm {
pid_t proc_pid;
struct task_struct *proc_task;
+ int touch_count;
+ bool touch_report_rate_config;
+ bool next_report_rate_config;
+ int last_vrefresh_rate;
+ struct delayed_work set_report_rate_work;
+
/* flags */
int pwr_state;
bool slept_in_early_suspend;
diff --git a/syna_tcm2_platform.h b/syna_tcm2_platform.h
index e38e5a2..8242d95 100644
--- a/syna_tcm2_platform.h
+++ b/syna_tcm2_platform.h
@@ -153,6 +153,7 @@ struct syna_hw_interface {
#endif
int udfps_x;
int udfps_y;
+ bool dynamic_report_rate;
/* Operation to do power on/off, if supported
*
diff --git a/syna_tcm2_platform_spi.c b/syna_tcm2_platform_spi.c
index b8ac888..d0a4098 100644
--- a/syna_tcm2_platform_spi.c
+++ b/syna_tcm2_platform_spi.c
@@ -696,6 +696,8 @@ static int syna_spi_parse_dt(struct syna_hw_interface *hw_if,
hw_if->compression_threhsold = 15;
}
+ hw_if->dynamic_report_rate = of_property_read_bool(np,"synaptics,dynamic-report-rate");
+
#if IS_ENABLED(CONFIG_TOUCHSCREEN_OFFLOAD)
hw_if->offload_id = 0;
retval = of_property_read_u8_array(np, "synaptics,touch_offload_id",
diff --git a/tcm/synaptics_touchcom_core_dev.h b/tcm/synaptics_touchcom_core_dev.h
index 9e136ba..0871dbc 100644
--- a/tcm/synaptics_touchcom_core_dev.h
+++ b/tcm/synaptics_touchcom_core_dev.h
@@ -121,6 +121,9 @@
#define RESP_IN_ATTN (1)
#define RESP_IN_POLLING (CMD_RESPONSE_POLLING_DELAY_MS)
+#define CONFIG_HIGH_REPORT_RATE 0
+#define CONFIG_LOW_REPORT_RATE 1
+
/**
* @section: Macro to show string in log
*/
@@ -221,6 +224,8 @@ enum dynamic_tcm_config_id {
DC_INHIBIT_ACTIVE_GESTURE = 0x0f,
DC_DISABLE_PROXIMITY = 0x10,
DC_HIGH_SENSITIVIRY_MODE = 0xCB,
+ /* Set 0 for high report rate(240Hz), 1 for low report rate(120Hz). */
+ DC_REPORT_RATE_SWITCH = 0xE6,
DC_FORCE_DOZE_MODE = 0xF0,
DC_COMPRESSION_THRESHOLD = 0xF1,
DC_TOUCH_SCAN_MODE = 0xF2,