summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWendly Li <wendlyli@google.com>2023-03-22 07:15:39 +0000
committerWendly Li <wendlyli@google.com>2023-03-22 07:16:37 +0000
commite42dc675eb1ebb1cf0e67653ca604743a51cb7e7 (patch)
treea0b3744d29fb992a9e708a89d14aff7065792ac5
parentf6f8d947b220e094ea67d3ecda81762a86403851 (diff)
parentcaacac38ecf3a00b7715817444a6cc490867413f (diff)
downloadcommon-e42dc675eb1ebb1cf0e67653ca604743a51cb7e7.tar.gz
Merge android14-gs-pixel-5.15 into android13-gs-pixel-5.10-udc
Change-Id: I7d71ff1eb648b32d7b68e54f8c52111e8662185a Signed-off-by: Wendly Li <wendlyli@google.com>
-rw-r--r--BUILD.bazel43
-rw-r--r--Kconfig8
-rw-r--r--goog_touch_interface.c973
-rw-r--r--goog_touch_interface.h110
-rw-r--r--include/uapi/input/touch_offload.h8
-rw-r--r--touch_bus_negotiator.c258
-rw-r--r--touch_bus_negotiator.h39
-rw-r--r--touch_offload.c6
8 files changed, 939 insertions, 506 deletions
diff --git a/BUILD.bazel b/BUILD.bazel
index bdbe919..295e884 100644
--- a/BUILD.bazel
+++ b/BUILD.bazel
@@ -1,12 +1,6 @@
-# NOTE: THIS FILE IS EXPERIMENTAL FOR THE BAZEL MIGRATION AND NOT USED FOR
-# YOUR BUILDS CURRENTLY.
-#
-# It is not yet the source of truth for your build. If you're looking to modify
-# the build file, modify the Android.bp file instead. Do *not* modify this file
-# unless you have coordinated with the team managing the Soong to Bazel
-# migration.
+# SPDX-License-Identifier: GPL-2.0-or-later
-load("//build/kleaf:kernel.bzl", "kernel_module")
+load("//build/kernel/kleaf:kernel.bzl", "kernel_module")
filegroup(
name = "headers",
@@ -18,16 +12,43 @@ filegroup(
],
)
+filegroup(
+ name = "touch.common.kconfig",
+ srcs = glob([
+ "Kconfig",
+ ]),
+ visibility = [
+ "//private/devices/google:__subpackages__",
+ "//private/google-modules/soc/gs:__pkg__",
+ ],
+)
+
kernel_module(
- name = "common.cloudripper",
+ name = "touch.common",
+ srcs = glob([
+ "**/*.c",
+ "**/*.h",
+ "Kbuild",
+ ]) + [
+ "//private/google-modules/aoc:headers",
+ "//private/google-modules/soc/gs:gs_soc_headers",
+ "//private/google-modules/display:headers",
+ "//private/google-modules/display/include:headers",
+ ],
outs = [
+ "goog_touch_interface.ko",
"heatmap.ko",
"touch_bus_negotiator.ko",
"touch_offload.ko",
],
- kernel_build = "//private/gs-google:cloudripper",
+ kernel_build = "//private/google-modules/soc/gs:gs_kernel_build",
visibility = [
+ "//private/devices/google:__subpackages__",
+ "//private/google-modules/soc/gs:__pkg__",
"//private/google-modules/touch:__subpackages__",
- "//private/gs-google:__pkg__",
+ ],
+ deps = [
+ "//private/google-modules/aoc",
+ "//private/google-modules/soc/gs:gs_soc_module",
],
)
diff --git a/Kconfig b/Kconfig
index 7636621..d121fa6 100644
--- a/Kconfig
+++ b/Kconfig
@@ -20,6 +20,14 @@ config TOUCHSCREEN_TBN
To compile this driver as a module, choose M here: the module will be
called touch_bus_negotiator.
+config TOUCHSCREEN_TBN_AOC_CHANNEL_MODE
+ bool "AOC channel mode for TBN"
+ depends on TOUCHSCREEN_TBN
+ help
+ Say Y here if you want to enable AOC channel mode for TBN.
+
+ If unsure, say N.
+
config TOUCHSCREEN_OFFLOAD
tristate "Touchscreen algorithm offload"
depends on (TOUCHSCREEN_FTS || TOUCHSCREEN_SEC_TS)
diff --git a/goog_touch_interface.c b/goog_touch_interface.c
index a996756..e39ae5b 100644
--- a/goog_touch_interface.c
+++ b/goog_touch_interface.c
@@ -8,6 +8,7 @@
#include <linux/module.h>
#include <linux/input/mt.h>
#include <linux/of.h>
+#include <linux/power_supply.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <samsung/exynos_drm_connector.h>
@@ -23,6 +24,7 @@ static u8 gti_dev_num;
* GTI/common: forward declarations, structures and functions.
*/
static void goog_offload_set_running(struct goog_touch_interface *gti, bool running);
+static void goog_lookup_touch_report_rate(struct goog_touch_interface *gti);
static int goog_precheck_heatmap(struct goog_touch_interface *gti);
static void goog_set_display_state(struct goog_touch_interface *gti,
enum gti_display_state_setting display_state);
@@ -325,6 +327,10 @@ static ssize_t force_active_show(
struct device *dev, struct device_attribute *attr, char *buf);
static ssize_t force_active_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size);
+static ssize_t fw_coord_filter_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+static ssize_t fw_coord_filter_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size);
static ssize_t fw_grip_show(struct device *dev,
struct device_attribute *attr, char *buf);
static ssize_t fw_grip_store(struct device *dev,
@@ -343,12 +349,6 @@ static ssize_t mf_mode_show(struct device *dev,
struct device_attribute *attr, char *buf);
static ssize_t mf_mode_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size);
-static ssize_t ms_base_show(struct device *dev,
- struct device_attribute *attr, char *buf);
-static ssize_t ms_diff_show(struct device *dev,
- struct device_attribute *attr, char *buf);
-static ssize_t ms_raw_show(struct device *dev,
- struct device_attribute *attr, char *buf);
static ssize_t offload_enabled_show(struct device *dev,
struct device_attribute *attr, char *buf);
static ssize_t offload_enabled_store(struct device *dev,
@@ -369,12 +369,6 @@ static ssize_t screen_protector_mode_enabled_show(struct device *dev,
struct device_attribute *attr, char *buf);
static ssize_t self_test_show(struct device *dev,
struct device_attribute *attr, char *buf);
-static ssize_t ss_base_show(struct device *dev,
- struct device_attribute *attr, char *buf);
-static ssize_t ss_diff_show(struct device *dev,
- struct device_attribute *attr, char *buf);
-static ssize_t ss_raw_show(struct device *dev,
- struct device_attribute *attr, char *buf);
static ssize_t sensing_enabled_show(struct device *dev,
struct device_attribute *attr, char *buf);
static ssize_t sensing_enabled_store(struct device *dev,
@@ -383,49 +377,45 @@ static ssize_t v4l2_enabled_show(struct device *dev,
struct device_attribute *attr, char *buf);
static ssize_t v4l2_enabled_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size);
+static ssize_t vrr_enabled_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+static ssize_t vrr_enabled_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size);
static DEVICE_ATTR_RW(force_active);
+static DEVICE_ATTR_RW(fw_coord_filter);
static DEVICE_ATTR_RW(fw_grip);
static DEVICE_ATTR_RW(fw_palm);
static DEVICE_ATTR_RO(fw_ver);
static DEVICE_ATTR_RW(irq_enabled);
static DEVICE_ATTR_RW(mf_mode);
-static DEVICE_ATTR_RO(ms_base);
-static DEVICE_ATTR_RO(ms_diff);
-static DEVICE_ATTR_RO(ms_raw);
static DEVICE_ATTR_RW(offload_enabled);
static DEVICE_ATTR_RO(ping);
static DEVICE_ATTR_RW(reset);
static DEVICE_ATTR_RW(scan_mode);
static DEVICE_ATTR_RW(screen_protector_mode_enabled);
static DEVICE_ATTR_RO(self_test);
-static DEVICE_ATTR_RO(ss_base);
-static DEVICE_ATTR_RO(ss_diff);
-static DEVICE_ATTR_RO(ss_raw);
static DEVICE_ATTR_RW(sensing_enabled);
static DEVICE_ATTR_RW(v4l2_enabled);
+static DEVICE_ATTR_RW(vrr_enabled);
static struct attribute *goog_attributes[] = {
&dev_attr_force_active.attr,
+ &dev_attr_fw_coord_filter.attr,
&dev_attr_fw_grip.attr,
&dev_attr_fw_palm.attr,
&dev_attr_fw_ver.attr,
&dev_attr_irq_enabled.attr,
&dev_attr_mf_mode.attr,
- &dev_attr_ms_base.attr,
- &dev_attr_ms_diff.attr,
- &dev_attr_ms_raw.attr,
&dev_attr_offload_enabled.attr,
&dev_attr_ping.attr,
&dev_attr_reset.attr,
&dev_attr_scan_mode.attr,
&dev_attr_screen_protector_mode_enabled.attr,
&dev_attr_self_test.attr,
- &dev_attr_ss_base.attr,
- &dev_attr_ss_diff.attr,
- &dev_attr_ss_raw.attr,
&dev_attr_sensing_enabled.attr,
&dev_attr_v4l2_enabled.attr,
+ &dev_attr_vrr_enabled.attr,
NULL,
};
@@ -496,6 +486,70 @@ static ssize_t force_active_store(struct device *dev,
return size;
}
+static ssize_t fw_coord_filter_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int ret = 0;
+ ssize_t buf_idx = 0;
+ struct goog_touch_interface *gti = dev_get_drvdata(dev);
+ struct gti_coord_filter_cmd *cmd = &gti->cmd.coord_filter_cmd;
+
+ if (!gti->coord_filter_enabled) {
+ buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
+ "error: not supported!\n");
+ GOOG_INFO(gti, "%s", buf);
+ return buf_idx;
+ }
+
+ cmd->setting = GTI_COORD_FILTER_DISABLE;
+ ret = goog_process_vendor_cmd(gti, GTI_CMD_GET_COORD_FILTER_ENABLED);
+ if (ret == -EOPNOTSUPP) {
+ buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
+ "error: not supported!\n");
+ } else if (ret) {
+ buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
+ "error: %d!\n", ret);
+ } else {
+ buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
+ "result: %u\n", cmd->setting | (gti->ignore_coord_filter_update << 1));
+ }
+ GOOG_INFO(gti, "%s", buf);
+
+ return buf_idx;
+}
+
+static ssize_t fw_coord_filter_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ int ret = 0;
+ struct goog_touch_interface *gti = dev_get_drvdata(dev);
+ int fw_coord_filter;
+
+ if (kstrtou32(buf, 10, &fw_coord_filter)) {
+ GOOG_INFO(gti, "error: invalid input!\n");
+ return -EINVAL;
+ }
+
+ if (!gti->coord_filter_enabled) {
+ GOOG_INFO(gti, "error: not supported!\n");
+ return -EOPNOTSUPP;
+ }
+
+ gti->fw_coord_filter_enabled = fw_coord_filter & 0x01;
+ gti->ignore_coord_filter_update = (fw_coord_filter >> 1) & 0x01;
+ gti->cmd.coord_filter_cmd.setting = gti->fw_coord_filter_enabled ?
+ GTI_COORD_FILTER_ENABLE : GTI_COORD_FILTER_DISABLE;
+ ret = goog_process_vendor_cmd(gti, GTI_CMD_SET_COORD_FILTER_ENABLED);
+ if (ret == -EOPNOTSUPP)
+ GOOG_INFO(gti, "error: not supported!\n");
+ else if (ret)
+ GOOG_INFO(gti, "error: %d!\n", ret);
+ else
+ GOOG_INFO(gti, "fw_coord_filter= %u\n", fw_coord_filter);
+
+ return size;
+}
+
static ssize_t fw_grip_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -713,171 +767,6 @@ static ssize_t mf_mode_store(struct device *dev,
return size;
}
-static ssize_t ms_base_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- ssize_t buf_idx = 0;
- struct goog_touch_interface *gti = dev_get_drvdata(dev);
- struct gti_sensor_data_cmd *cmd = &gti->cmd.manual_sensor_data_cmd;
- int ret = 0;
- u16 tx = gti->offload.caps.tx_size;
- u16 rx = gti->offload.caps.rx_size;
- int x, y;
-
- ret = goog_precheck_heatmap(gti);
- if (ret) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
- "result: N/A!\n");
- return buf_idx;
- }
-
- ret = mutex_lock_interruptible(&gti->input_process_lock);
- if (ret != 0) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
- "error: has been interrupted!\n");
- return buf_idx;
- }
-
- cmd->type = GTI_SENSOR_DATA_TYPE_MS_BASELINE;
- cmd->buffer = NULL;
- cmd->size = 0;
- ret = goog_process_vendor_cmd(gti, GTI_CMD_GET_SENSOR_DATA_MANUAL);
- if (ret == -EOPNOTSUPP) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
- "error: not supported!\n");
- } else if (ret) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
- "error: %d!\n", ret);
- } else {
- u8 width = GTI_SENSOR_2D_OUT_FORMAT_WIDTH(cmd->size);
-
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx, "result:\n");
- if (cmd->buffer && cmd->size == TOUCH_OFFLOAD_DATA_SIZE_2D(rx, tx)) {
- for (y = 0; y < rx; y++) {
- for (x = 0; x < tx; x++) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
- "%*d,", width, ((s16 *)cmd->buffer)[y * tx + x]);
- }
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx, "\n");
- }
- GOOG_INFO(gti, "%s", buf);
- }
- }
-
- mutex_unlock(&gti->input_process_lock);
- return buf_idx;
-}
-
-static ssize_t ms_diff_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- ssize_t buf_idx = 0;
- struct goog_touch_interface *gti = dev_get_drvdata(dev);
- struct gti_sensor_data_cmd *cmd = &gti->cmd.manual_sensor_data_cmd;
- int ret = 0;
- u16 tx = gti->offload.caps.tx_size;
- u16 rx = gti->offload.caps.rx_size;
- int x, y;
-
- ret = goog_precheck_heatmap(gti);
- if (ret) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
- "result: N/A!\n");
- return buf_idx;
- }
-
- ret = mutex_lock_interruptible(&gti->input_process_lock);
- if (ret != 0) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
- "error: has been interrupted!\n");
- return buf_idx;
- }
-
- cmd->type = GTI_SENSOR_DATA_TYPE_MS_DIFF;
- cmd->buffer = NULL;
- cmd->size = 0;
- ret = goog_process_vendor_cmd(gti, GTI_CMD_GET_SENSOR_DATA_MANUAL);
- if (ret == -EOPNOTSUPP) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
- "error: not supported!\n");
- } else if (ret) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
- "error: %d!\n", ret);
- } else {
- u8 width = GTI_SENSOR_2D_OUT_FORMAT_WIDTH(cmd->size);
-
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx, "result:\n");
- if (cmd->buffer && cmd->size == TOUCH_OFFLOAD_DATA_SIZE_2D(rx, tx)) {
- for (y = 0; y < rx; y++) {
- for (x = 0; x < tx; x++) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
- "%*d,", width, ((s16 *)cmd->buffer)[y * tx + x]);
- }
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx, "\n");
- }
- GOOG_INFO(gti, "%s", buf);
- }
- }
-
- mutex_unlock(&gti->input_process_lock);
- return buf_idx;
-}
-
-static ssize_t ms_raw_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- ssize_t buf_idx = 0;
- struct goog_touch_interface *gti = dev_get_drvdata(dev);
- struct gti_sensor_data_cmd *cmd = &gti->cmd.manual_sensor_data_cmd;
- int ret = 0;
- u16 tx = gti->offload.caps.tx_size;
- u16 rx = gti->offload.caps.rx_size;
- int x, y;
-
- ret = goog_precheck_heatmap(gti);
- if (ret) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
- "result: N/A!\n");
- return buf_idx;
- }
-
- ret = mutex_lock_interruptible(&gti->input_process_lock);
- if (ret != 0) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
- "error: has been interrupted!\n");
- return buf_idx;
- }
-
- cmd->type = GTI_SENSOR_DATA_TYPE_MS_RAW;
- cmd->buffer = NULL;
- cmd->size = 0;
- ret = goog_process_vendor_cmd(gti, GTI_CMD_GET_SENSOR_DATA_MANUAL);
- if (ret == -EOPNOTSUPP) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
- "error: not supported!\n");
- } else if (ret) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
- "error: %d!\n", ret);
- } else {
- u8 width = GTI_SENSOR_2D_OUT_FORMAT_WIDTH(cmd->size);
-
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx, "result:\n");
- if (cmd->buffer && cmd->size == TOUCH_OFFLOAD_DATA_SIZE_2D(rx, tx)) {
- for (y = 0; y < rx; y++) {
- for (x = 0; x < tx; x++) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
- "%*d,", width, ((s16 *)cmd->buffer)[y * tx + x]);
- }
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx, "\n");
- }
- GOOG_INFO(gti, "%s", buf);
- }
- }
-
- mutex_unlock(&gti->input_process_lock);
- return buf_idx;
-}
-
static ssize_t offload_enabled_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -1129,183 +1018,6 @@ static ssize_t self_test_show(struct device *dev,
return buf_idx;
}
-static ssize_t ss_base_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- ssize_t buf_idx = 0;
- struct goog_touch_interface *gti = dev_get_drvdata(dev);
- struct gti_sensor_data_cmd *cmd = &gti->cmd.manual_sensor_data_cmd;
- int ret = 0;
- u16 tx = gti->offload.caps.tx_size;
- u16 rx = gti->offload.caps.rx_size;
- int x, y;
-
- ret = goog_precheck_heatmap(gti);
- if (ret) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
- "result: N/A!\n");
- return buf_idx;
- }
-
- ret = mutex_lock_interruptible(&gti->input_process_lock);
- if (ret != 0) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
- "error: has been interrupted!\n");
- return buf_idx;
- }
-
- cmd->type = GTI_SENSOR_DATA_TYPE_SS_BASELINE;
- cmd->buffer = NULL;
- cmd->size = 0;
- ret = goog_process_vendor_cmd(gti, GTI_CMD_GET_SENSOR_DATA_MANUAL);
- if (ret == -EOPNOTSUPP) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
- "error: not supported!\n");
- } else if (ret) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
- "error: %d!\n", ret);
- } else {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx, "result:\n");
- if (cmd->buffer &&
- cmd->size == TOUCH_OFFLOAD_DATA_SIZE_1D(rx, tx)) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx, "TX:");
- for (x = 0; x < tx; x++) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
- "%5d,", ((s16 *)cmd->buffer)[x]);
- }
-
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx, "\nRX:");
- for (y = 0; y < rx; y++) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
- "%5d,", ((s16 *)cmd->buffer)[tx + y]);
- }
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx, "\n");
- GOOG_INFO(gti, "%s", buf);
- }
- }
-
- mutex_unlock(&gti->input_process_lock);
- return buf_idx;
-}
-
-static ssize_t ss_diff_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- ssize_t buf_idx = 0;
- struct goog_touch_interface *gti = dev_get_drvdata(dev);
- struct gti_sensor_data_cmd *cmd = &gti->cmd.manual_sensor_data_cmd;
- int ret = 0;
- u16 tx = gti->offload.caps.tx_size;
- u16 rx = gti->offload.caps.rx_size;
- int x, y;
-
- ret = goog_precheck_heatmap(gti);
- if (ret) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
- "result: N/A!\n");
- return buf_idx;
- }
-
- ret = mutex_lock_interruptible(&gti->input_process_lock);
- if (ret != 0) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
- "error: has been interrupted!\n");
- return buf_idx;
- }
-
- cmd->type = GTI_SENSOR_DATA_TYPE_SS_DIFF;
- cmd->buffer = NULL;
- cmd->size = 0;
- ret = goog_process_vendor_cmd(gti, GTI_CMD_GET_SENSOR_DATA_MANUAL);
- if (ret == -EOPNOTSUPP) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
- "error: not supported!\n");
- } else if (ret) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
- "error: %d!\n", ret);
- } else {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx, "result:\n");
- if (cmd->buffer &&
- cmd->size == TOUCH_OFFLOAD_DATA_SIZE_1D(rx, tx)) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx, "TX:");
- for (x = 0; x < tx; x++) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
- "%5d,", ((s16 *)cmd->buffer)[x]);
- }
-
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx, "\nRX:");
- for (y = 0; y < rx; y++) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
- "%5d,", ((s16 *)cmd->buffer)[tx + y]);
- }
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx, "\n");
- GOOG_INFO(gti, "%s", buf);
- }
- }
-
- mutex_unlock(&gti->input_process_lock);
- return buf_idx;
-}
-
-static ssize_t ss_raw_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- ssize_t buf_idx = 0;
- struct goog_touch_interface *gti = dev_get_drvdata(dev);
- struct gti_sensor_data_cmd *cmd = &gti->cmd.manual_sensor_data_cmd;
- int ret = 0;
- u16 tx = gti->offload.caps.tx_size;
- u16 rx = gti->offload.caps.rx_size;
- int x, y;
-
- ret = goog_precheck_heatmap(gti);
- if (ret) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
- "result: N/A!\n");
- return buf_idx;
- }
-
- ret = mutex_lock_interruptible(&gti->input_process_lock);
- if (ret != 0) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
- "error: has been interrupted!\n");
- return buf_idx;
- }
-
- cmd->type = GTI_SENSOR_DATA_TYPE_SS_RAW;
- cmd->buffer = NULL;
- cmd->size = 0;
- ret = goog_process_vendor_cmd(gti, GTI_CMD_GET_SENSOR_DATA_MANUAL);
- if (ret == -EOPNOTSUPP) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
- "error: not supported!\n");
- } else if (ret) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
- "error: %d!\n", ret);
- } else {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx, "result:\n");
- if (cmd->buffer &&
- cmd->size == TOUCH_OFFLOAD_DATA_SIZE_1D(rx, tx)) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx, "TX:");
- for (x = 0; x < tx; x++) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
- "%5d,", ((s16 *)cmd->buffer)[x]);
- }
-
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx, "\nRX:");
- for (y = 0; y < rx; y++) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
- "%5d,", ((s16 *)cmd->buffer)[tx + y]);
- }
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx, "\n");
- GOOG_INFO(gti, "%s", buf);
- }
- }
-
- mutex_unlock(&gti->input_process_lock);
- return buf_idx;
-}
-
static ssize_t sensing_enabled_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -1380,6 +1092,37 @@ static ssize_t v4l2_enabled_store(struct device *dev,
return size;
}
+static ssize_t vrr_enabled_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t buf_idx = 0;
+ struct goog_touch_interface *gti = dev_get_drvdata(dev);
+
+ buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE,
+ "result: %d\n", gti->vrr_enabled);
+ GOOG_INFO(gti, "%s", buf);
+
+ return buf_idx;
+}
+
+static ssize_t vrr_enabled_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct goog_touch_interface *gti = dev_get_drvdata(dev);
+
+ if (kstrtobool(buf, &gti->vrr_enabled)) {
+ GOOG_INFO(gti, "error: invalid input!\n");
+ } else if (gti->report_rate_table_size == 0) {
+ GOOG_INFO(gti, "error: No valid report rate table!\n");
+ } else {
+ GOOG_INFO(gti, "vrr_enabled= %d\n", gti->vrr_enabled);
+ if (gti->vrr_enabled)
+ goog_lookup_touch_report_rate(gti);
+ }
+
+ return size;
+}
+
/*-----------------------------------------------------------------------------
* Debug: functions.
*/
@@ -1479,6 +1222,7 @@ inline int gti_debug_input_pop(struct goog_touch_interface *gti,
GOOG_ERR(gti, "invalid fifo pop len(%d)!\n", len);
return -EINVAL;
}
+
/*
* Keep coords without pop-out to support different timing
* print-out by each caller.
@@ -1655,9 +1399,9 @@ static void panel_bridge_mode_set(struct drm_bridge *bridge,
panel_is_lp_mode = panel_bridge_is_lp_mode(gti->connector);
if (gti->panel_is_lp_mode != panel_is_lp_mode) {
-
GOOG_INFO(gti, "panel_is_lp_mode changed from %d to %d.\n",
gti->panel_is_lp_mode, panel_is_lp_mode);
+
if (panel_is_lp_mode)
goog_set_display_state(gti, GTI_DISPLAY_STATE_OFF);
else
@@ -1673,9 +1417,13 @@ static void panel_bridge_mode_set(struct drm_bridge *bridge,
vrefresh, gti->display_vrefresh);
gti->display_vrefresh = vrefresh;
gti->cmd.display_vrefresh_cmd.setting = vrefresh;
+ gti->context_changed.display_refresh_rate = 1;
ret = goog_process_vendor_cmd(gti, GTI_CMD_NOTIFY_DISPLAY_VREFRESH);
if (ret && ret != -EOPNOTSUPP)
GOOG_WARN(gti, "unexpected return(%d)!", ret);
+
+ if (gti->vrr_enabled)
+ goog_lookup_touch_report_rate(gti);
}
}
}
@@ -1730,24 +1478,13 @@ static int goog_precheck_heatmap(struct goog_touch_interface *gti)
{
int ret = 0;
- if (gti->display_state == GTI_DISPLAY_STATE_OFF) {
- /*
- * Ignore request on heatamp if project correlates closely with
- * display for touch scanning or I/O transaction.
- */
- if (gti->ignore_screenoff_heatmap) {
- GOOG_WARN(gti, "N/A for screen-off!\n");
- ret = -ENODATA;
- }
-
- /*
- * Check the PM wakelock state for bus ownership before data
- * request.
- */
- if (!goog_pm_wake_get_locks(gti)) {
- GOOG_WARN(gti, "N/A during inactive bus!\n");
- ret = -ENODATA;
- }
+ /*
+ * Check the PM wakelock state and pm state for bus ownership before
+ * data request.
+ */
+ if (!goog_pm_wake_get_locks(gti) || gti->pm.state == GTI_PM_SUSPEND) {
+ GOOG_WARN(gti, "N/A during inactive bus!\n");
+ ret = -ENODATA;
}
return ret;
@@ -1781,6 +1518,8 @@ static void goog_set_display_state(struct goog_touch_interface *gti,
display_state);
return;
}
+
+ gti->context_changed.screen_state = 1;
gti->display_state = display_state;
gti->cmd.display_state_cmd.setting = display_state;
ret = goog_process_vendor_cmd(gti, GTI_CMD_NOTIFY_DISPLAY_STATE);
@@ -1828,6 +1567,10 @@ int goog_process_vendor_cmd(struct goog_touch_interface *gti, enum gti_cmd_type
case GTI_CMD_GET_CONTEXT_STYLUS:
ret = gti->options.get_context_stylus(private_data, &gti->cmd.context_stylus_cmd);
break;
+ case GTI_CMD_GET_COORD_FILTER_ENABLED:
+ ret = gti->options.get_coord_filter_enabled(private_data,
+ &gti->cmd.coord_filter_cmd);
+ break;
case GTI_CMD_GET_FW_VERSION:
ret = gti->options.get_fw_version(private_data, &gti->cmd.fw_version_cmd);
break;
@@ -1880,7 +1623,14 @@ int goog_process_vendor_cmd(struct goog_touch_interface *gti, enum gti_cmd_type
ret = gti->options.set_continuous_report(private_data,
&gti->cmd.continuous_report_cmd);
break;
+ case GTI_CMD_SET_COORD_FILTER_ENABLED:
+ ret = gti->options.set_coord_filter_enabled(private_data,
+ &gti->cmd.coord_filter_cmd);
+ break;
case GTI_CMD_SET_GRIP_MODE:
+ GOOG_INFO(gti, "Set firmware grip %s",
+ gti->cmd.grip_cmd.setting == GTI_GRIP_ENABLE ?
+ "enabled" : "disabled");
ret = gti->options.set_grip_mode(private_data, &gti->cmd.grip_cmd);
break;
case GTI_CMD_SET_HEATMAP_ENABLED:
@@ -1890,13 +1640,25 @@ int goog_process_vendor_cmd(struct goog_touch_interface *gti, enum gti_cmd_type
ret = gti->options.set_irq_mode(private_data, &gti->cmd.irq_cmd);
break;
case GTI_CMD_SET_PALM_MODE:
+ GOOG_INFO(gti, "Set firmware palm %s",
+ gti->cmd.palm_cmd.setting == GTI_PALM_ENABLE ?
+ "enabled" : "disabled");
ret = gti->options.set_palm_mode(private_data, &gti->cmd.palm_cmd);
break;
+ case GTI_CMD_SET_REPORT_RATE:
+ GOOG_INFO(gti, "Set touch report rate as %d Hz", gti->cmd.report_rate_cmd.setting);
+ ret = gti->options.set_report_rate(private_data, &gti->cmd.report_rate_cmd);
+ break;
case GTI_CMD_SET_SCAN_MODE:
ret = gti->options.set_scan_mode(private_data, &gti->cmd.scan_cmd);
break;
case GTI_CMD_SET_SCREEN_PROTECTOR_MODE:
- ret = gti->options.set_screen_protector_mode(private_data, &gti->cmd.screen_protector_mode_cmd);
+ GOOG_INFO(gti, "Set screen protector mode %s",
+ gti->cmd.screen_protector_mode_cmd.setting ==
+ GTI_SCREEN_PROTECTOR_MODE_ENABLE
+ ? "enabled" : "disabled");
+ ret = gti->options.set_screen_protector_mode(private_data,
+ &gti->cmd.screen_protector_mode_cmd);
break;
case GTI_CMD_SET_SENSING_MODE:
ret = gti->options.set_sensing_mode(private_data, &gti->cmd.sensing_cmd);
@@ -1913,6 +1675,9 @@ int goog_process_vendor_cmd(struct goog_touch_interface *gti, enum gti_cmd_type
if (ret == -EOPNOTSUPP) {
GOOG_DBG(gti, "unsupported request cmd_type %#x!\n", cmd_type);
ret = 0;
+ } else if (ret == -ESRCH) {
+ GOOG_WARN(gti, "No handler for cmd_type %#x!\n", cmd_type);
+ ret = 0;
}
return ret;
@@ -2005,6 +1770,24 @@ void goog_v4l2_read(struct goog_touch_interface *gti, ktime_t timestamp)
heatmap_read(&gti->v4l2, ktime_to_ns(timestamp));
}
+int goog_get_driver_status(struct goog_touch_interface *gti,
+ struct gti_context_driver_cmd *driver_cmd)
+{
+ gti->context_changed.offload_timestamp = 1;
+
+ driver_cmd->context_changed.value = gti->context_changed.value;
+ driver_cmd->screen_state = gti->display_state;
+ driver_cmd->display_refresh_rate = gti->display_vrefresh;
+ driver_cmd->touch_report_rate = gti->report_rate_setting;
+ driver_cmd->noise_state = gti->fw_status.noise_level;
+ driver_cmd->water_mode = gti->fw_status.water_mode;
+ driver_cmd->charger_state = gti->charger_state;
+ driver_cmd->offload_timestamp = ktime_get();
+
+ /* vendor driver overwrite the context */
+ return goog_process_vendor_cmd(gti, GTI_CMD_GET_CONTEXT_DRIVER);
+}
+
void goog_offload_populate_coordinate_channel(struct goog_touch_interface *gti,
struct touch_offload_frame *frame, int channel)
{
@@ -2084,17 +1867,25 @@ static void goog_offload_populate_driver_status_channel(
ds->header.channel_type = (u32)CONTEXT_CHANNEL_TYPE_DRIVER_STATUS;
ds->header.channel_size = sizeof(struct TouchOffloadDriverStatus);
- ds->contents.screen_state = driver_cmd->contents.screen_state;
+ ds->contents.screen_state = driver_cmd->context_changed.screen_state;
ds->screen_state = driver_cmd->screen_state;
- ds->contents.display_refresh_rate =
- driver_cmd->contents.display_refresh_rate;
+ ds->contents.display_refresh_rate = driver_cmd->context_changed.display_refresh_rate;
ds->display_refresh_rate = driver_cmd->display_refresh_rate;
- ds->contents.touch_report_rate = driver_cmd->contents.touch_report_rate;
+ ds->contents.touch_report_rate = driver_cmd->context_changed.touch_report_rate;
ds->touch_report_rate = driver_cmd->touch_report_rate;
- ds->contents.offload_timestamp = driver_cmd->contents.offload_timestamp;
+ ds->contents.noise_state = driver_cmd->context_changed.noise_state;
+ ds->noise_state = driver_cmd->noise_state;
+
+ ds->contents.water_mode = driver_cmd->context_changed.water_mode;
+ ds->water_mode = driver_cmd->water_mode;
+
+ ds->contents.charger_state = driver_cmd->context_changed.charger_state;
+ ds->charger_state = driver_cmd->charger_state;
+
+ ds->contents.offload_timestamp = driver_cmd->context_changed.offload_timestamp;
ds->offload_timestamp = driver_cmd->offload_timestamp;
}
@@ -2123,8 +1914,52 @@ static void goog_offload_populate_stylus_status_channel(
ss->pen_active = stylus_cmd->pen_active;
}
+static int goog_get_sensor_data(struct goog_touch_interface *gti,
+ struct gti_sensor_data_cmd *cmd, bool reset_data)
+{
+ int ret = 0;
+ int err = 0;
+ u16 tx = gti->offload.caps.tx_size;
+ u16 rx = gti->offload.caps.rx_size;
+
+ if (reset_data) {
+ if (cmd->type == GTI_SENSOR_DATA_TYPE_MS) {
+ cmd->size = TOUCH_OFFLOAD_DATA_SIZE_2D(rx, tx);
+ } else if (cmd->type == GTI_SENSOR_DATA_TYPE_SS) {
+ cmd->size = TOUCH_OFFLOAD_DATA_SIZE_1D(rx, tx);
+ } else {
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ memset(gti->heatmap_buf, 0, cmd->size);
+ cmd->buffer = gti->heatmap_buf;
+ goto exit;
+ }
+
+ err = goog_pm_wake_lock(gti, GTI_PM_WAKELOCK_TYPE_SENSOR_DATA, true);
+ if (err < 0) {
+ GOOG_WARN(gti, "Failed to lock GTI_PM_WAKELOCK_TYPE_SENSOR_DATA: %d!\n", err);
+ ret = err;
+ goto exit;
+ }
+
+ err = goog_process_vendor_cmd(gti, GTI_CMD_GET_SENSOR_DATA);
+ if (err < 0) {
+ GOOG_WARN(gti, "Failed to get sensor data: %d!\n", err);
+ ret = err;
+ }
+
+ err = goog_pm_wake_unlock(gti, GTI_PM_WAKELOCK_TYPE_SENSOR_DATA);
+ if (err < 0)
+ GOOG_WARN(gti, "Failed to unlock GTI_PM_WAKELOCK_TYPE_SENSOR_DATA: %d!\n", err);
+
+exit:
+ return ret;
+}
+
void goog_offload_populate_frame(struct goog_touch_interface *gti,
- struct touch_offload_frame *frame, bool report_from_irq)
+ struct touch_offload_frame *frame, bool reset_data)
{
static u64 index;
char trace_tag[128];
@@ -2157,7 +1992,7 @@ void goog_offload_populate_frame(struct goog_touch_interface *gti,
cmd->size = 0;
if (channel_type == CONTEXT_CHANNEL_TYPE_DRIVER_STATUS) {
ATRACE_BEGIN("populate driver context");
- ret = goog_process_vendor_cmd(gti, GTI_CMD_GET_CONTEXT_DRIVER);
+ ret = goog_get_driver_status(gti, &gti->cmd.context_driver_cmd);
if (ret == 0)
goog_offload_populate_driver_status_channel(
gti, frame, i,
@@ -2178,14 +2013,8 @@ void goog_offload_populate_frame(struct goog_touch_interface *gti,
} else if (channel_type & TOUCH_SCAN_TYPE_MUTUAL) {
ATRACE_BEGIN("populate mutual data");
cmd->type = GTI_SENSOR_DATA_TYPE_MS;
- if (!report_from_irq) {
- cmd->size = TOUCH_OFFLOAD_DATA_SIZE_2D(rx, tx);
- memset(gti->heatmap_buf, 0, cmd->size);
- cmd->buffer = gti->heatmap_buf;
- ret = 0;
- } else {
- ret = goog_process_vendor_cmd(gti, GTI_CMD_GET_SENSOR_DATA);
- }
+
+ ret = goog_get_sensor_data(gti, cmd, reset_data);
if (ret == 0 && cmd->buffer &&
cmd->size == TOUCH_OFFLOAD_DATA_SIZE_2D(rx, tx)) {
goog_offload_populate_mutual_channel(gti, frame, i,
@@ -2198,14 +2027,8 @@ void goog_offload_populate_frame(struct goog_touch_interface *gti,
} else if (channel_type & TOUCH_SCAN_TYPE_SELF) {
ATRACE_BEGIN("populate self data");
cmd->type = GTI_SENSOR_DATA_TYPE_SS;
- if (!report_from_irq) {
- cmd->size = TOUCH_OFFLOAD_DATA_SIZE_1D(rx, tx);
- memset(gti->heatmap_buf, 0, cmd->size);
- cmd->buffer = gti->heatmap_buf;
- ret = 0;
- } else {
- ret = goog_process_vendor_cmd(gti, GTI_CMD_GET_SENSOR_DATA);
- }
+
+ ret = goog_get_sensor_data(gti, cmd, reset_data);
if (ret == 0 && cmd->buffer &&
cmd->size == TOUCH_OFFLOAD_DATA_SIZE_1D(rx, tx)) {
goog_offload_populate_self_channel(gti, frame, i,
@@ -2228,6 +2051,8 @@ void goog_offload_populate_frame(struct goog_touch_interface *gti,
void goog_update_fw_settings(struct goog_touch_interface *gti)
{
int ret = 0;
+ bool enabled = false;
+
if(!gti->ignore_grip_update) {
if (gti->offload.offload_running && gti->offload.config.filter_grip)
gti->cmd.grip_cmd.setting = GTI_GRIP_DISABLE;
@@ -2248,6 +2073,23 @@ void goog_update_fw_settings(struct goog_touch_interface *gti)
GOOG_WARN(gti, "unexpected return(%d)!", ret);
}
+ if (gti->coord_filter_enabled) {
+ if (!gti->ignore_coord_filter_update) {
+ if (gti->offload.offload_running && gti->offload.config.coord_filter)
+ enabled = false;
+ else
+ enabled = gti->default_coord_filter_enabled;
+ } else {
+ enabled = gti->fw_coord_filter_enabled;
+ }
+
+ gti->cmd.coord_filter_cmd.setting = enabled ?
+ GTI_COORD_FILTER_ENABLE : GTI_COORD_FILTER_DISABLE;
+ ret = goog_process_vendor_cmd(gti, GTI_CMD_SET_COORD_FILTER_ENABLED);
+ if (ret)
+ GOOG_WARN(gti, "unexpected return(%d)!", ret);
+ }
+
gti->cmd.screen_protector_mode_cmd.setting = gti->screen_protector_mode_setting;
ret = goog_process_vendor_cmd(gti, GTI_CMD_SET_SCREEN_PROTECTOR_MODE);
if (ret != 0)
@@ -2259,12 +2101,21 @@ void goog_update_fw_settings(struct goog_touch_interface *gti)
ret = goog_process_vendor_cmd(gti, GTI_CMD_SET_HEATMAP_ENABLED);
if (ret != 0)
GOOG_ERR(gti, "Failed to enable heatmap!\n");
+
+ if (gti->vrr_enabled) {
+ gti->cmd.report_rate_cmd.setting = gti->report_rate_setting_next;
+ ret = goog_process_vendor_cmd(gti, GTI_CMD_SET_REPORT_RATE);
+ if (ret != 0)
+ GOOG_ERR(gti, "Failed to set report rate!\n");
+ }
}
static void goog_offload_set_running(struct goog_touch_interface *gti, bool running)
{
if (gti->offload.offload_running != running) {
- GOOG_LOG(gti, "Offload state Changed: %d", running);
+ GOOG_INFO(gti, "Set offload_running=%d, irq_index=%d, input_index=%d\n",
+ running, gti->irq_index, gti->input_index);
+
gti->offload.offload_running = running;
goog_update_fw_settings(gti);
}
@@ -2351,6 +2202,38 @@ void goog_offload_input_report(void *handle,
ATRACE_END();
}
+int gti_charger_state_change(struct notifier_block *nb, unsigned long action,
+ void *data)
+{
+ struct goog_touch_interface *gti =
+ (struct goog_touch_interface *)container_of(nb,
+ struct goog_touch_interface, charger_notifier);
+ struct power_supply *psy = (struct power_supply *)data;
+ int ret;
+
+ /* Attempt actual status parsing */
+ if (psy && psy->desc->type == POWER_SUPPLY_TYPE_USB) {
+ union power_supply_propval present_val = { 0 };
+
+ ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_PRESENT,
+ &present_val);
+ if (ret < 0)
+ GOOG_ERR(gti,
+ "Error while getting power supply property: %d!\n",
+ ret);
+ else if ((u8)present_val.intval != gti->charger_state) {
+ /* Note: the expected values for present_val.intval are
+ * 0 and 1. Cast to unsigned byte to ensure the
+ * comparison is handled in the same variable data type.
+ */
+ gti->context_changed.charger_state = 1;
+ gti->charger_state = (u8)present_val.intval;
+ }
+ }
+
+ return 0;
+}
+
int goog_offload_probe(struct goog_touch_interface *gti)
{
int ret;
@@ -2433,6 +2316,8 @@ int goog_offload_probe(struct goog_touch_interface *gti)
gti->offload.caps.size_reporting = true;
gti->offload.caps.filter_grip = true;
gti->offload.caps.filter_palm = true;
+ gti->offload.caps.coord_filter = gti->coord_filter_enabled &&
+ of_property_read_bool(np, "goog,offload-caps-coord-filter");
gti->offload.caps.num_sensitivity_settings = 1;
gti->offload.caps.rotation_reporting = of_property_read_bool(np,
"goog,offload-caps-rotation-reporting");
@@ -2458,6 +2343,9 @@ int goog_offload_probe(struct goog_touch_interface *gti)
"goog,default-grip-disabled") ? GTI_GRIP_DISABLE : GTI_GRIP_ENABLE;
gti->default_palm_enabled = of_property_read_bool(np,
"goog,default-palm-disabled") ? GTI_PALM_DISABLE : GTI_PALM_ENABLE;
+ gti->default_coord_filter_enabled = of_property_read_bool(np,
+ "goog,default-coord-filter-disabled") ?
+ GTI_COORD_FILTER_DISABLE : GTI_COORD_FILTER_ENABLE;
gti->heatmap_buf_size = gti->offload.caps.tx_size * gti->offload.caps.rx_size * sizeof(u16);
gti->heatmap_buf = devm_kzalloc(gti->vendor_dev, gti->heatmap_buf_size, GFP_KERNEL);
@@ -2494,6 +2382,14 @@ int goog_offload_probe(struct goog_touch_interface *gti)
GOOG_INFO(gti, "v4l2 W/H=(%lu, %lu), v4l2_enabled=%d.\n",
gti->v4l2.width, gti->v4l2.height, gti->v4l2_enabled);
+ /* Register for charger plugging status */
+ gti->charger_notifier.notifier_call = gti_charger_state_change;
+ ret = power_supply_reg_notifier(&gti->charger_notifier);
+ if (!ret) {
+ GOOG_ERR(gti, "Failed to register power_supply_reg_notifier!\n");
+ goto err_offload_probe;
+ }
+
err_offload_probe:
return ret;
}
@@ -2511,17 +2407,17 @@ bool goog_input_legacy_report(struct goog_touch_interface *gti)
return false;
}
-int goog_input_process(struct goog_touch_interface *gti, bool report_from_irq)
+int goog_input_process(struct goog_touch_interface *gti, bool reset_data)
{
int ret = 0;
struct touch_offload_frame **frame = &gti->offload_frame;
/*
* Only do the input process if active slot(s) update
- * or slot(s) state change.
+ * or slot(s) state change or resetting frame data.
*/
if (!(gti->slot_bit_active & gti->slot_bit_in_use) &&
- !gti->slot_bit_changed)
+ !gti->slot_bit_changed && !reset_data)
return -EPERM;
/*
@@ -2534,7 +2430,8 @@ int goog_input_process(struct goog_touch_interface *gti, bool report_from_irq)
if (gti->offload_enabled) {
ret = touch_offload_reserve_frame(&gti->offload, frame);
if (ret != 0 || frame == NULL) {
- GOOG_ERR(gti, "could not reserve a frame(ret %d)!\n", ret);
+ GOOG_DBG(gti, "could not reserve a frame(ret %d)!\n", ret);
+
/* Stop offload when there are no buffers available. */
goog_offload_set_running(gti, false);
/*
@@ -2545,7 +2442,7 @@ int goog_input_process(struct goog_touch_interface *gti, bool report_from_irq)
ret = -EBUSY;
} else {
goog_offload_set_running(gti, true);
- goog_offload_populate_frame(gti, *frame, report_from_irq);
+ goog_offload_populate_frame(gti, *frame, reset_data);
ret = touch_offload_queue_frame(&gti->offload, *frame);
if (ret)
GOOG_ERR(gti, "failed to queue reserved frame(ret %d)!\n", ret);
@@ -2567,7 +2464,7 @@ int goog_input_process(struct goog_touch_interface *gti, bool report_from_irq)
cmd->buffer = NULL;
cmd->size = 0;
cmd->type = GTI_SENSOR_DATA_TYPE_MS;
- ret = goog_process_vendor_cmd(gti, GTI_CMD_GET_SENSOR_DATA);
+ ret = goog_get_sensor_data(gti, cmd, reset_data);
if (ret == 0 && cmd->buffer && cmd->size)
memcpy(gti->heatmap_buf, cmd->buffer, cmd->size);
goog_v4l2_read(gti, gti->input_timestamp);
@@ -2729,9 +2626,7 @@ void goog_input_release_all_fingers(struct goog_touch_interface *gti)
goog_input_unlock(gti);
- mutex_lock(&gti->input_process_lock);
- goog_input_process(gti, false);
- mutex_unlock(&gti->input_process_lock);
+ goog_input_process(gti, true);
}
void goog_register_tbn(struct goog_touch_interface *gti)
@@ -2761,6 +2656,12 @@ static int goog_get_context_stylus_nop(
return -ESRCH;
}
+static int goog_get_coord_filter_enabled_nop(
+ void *private_data, struct gti_coord_filter_cmd *cmd)
+{
+ return -ESRCH;
+}
+
static int goog_get_fw_version_nop(
void *private_data, struct gti_fw_version_cmd *cmd)
{
@@ -2851,6 +2752,12 @@ static int goog_set_continuous_report_nop(
return -ESRCH;
}
+static int goog_set_coord_filter_enabled_nop(
+ void *private_data, struct gti_coord_filter_cmd *cmd)
+{
+ return -ESRCH;
+}
+
static int goog_set_grip_mode_nop(
void *private_data, struct gti_grip_cmd *cmd)
{
@@ -2875,6 +2782,12 @@ static int goog_set_palm_mode_nop(
return -ESRCH;
}
+static int goog_set_report_rate_nop(
+ void *private_data, struct gti_report_rate_cmd *cmd)
+{
+ return -ESRCH;
+}
+
static int goog_set_scan_mode_nop(
void *private_data, struct gti_scan_cmd *cmd)
{
@@ -2953,17 +2866,21 @@ void goog_init_options(struct goog_touch_interface *gti,
struct gti_optional_configuration *options)
{
/* Initialize the common features. */
+ gti->mf_mode = GTI_MF_MODE_DEFAULT;
+ gti->screen_protector_mode_setting = GTI_SCREEN_PROTECTOR_MODE_DISABLE;
+ gti->display_state = GTI_DISPLAY_STATE_ON;
+
if (gti->vendor_dev) {
struct device_node *np = gti->vendor_dev->of_node;
gti->ignore_force_active = of_property_read_bool(np, "goog,ignore-force-active");
- gti->ignore_screenoff_heatmap =
- of_property_read_bool(np, "goog,ignore-screenoff-heatmap");
+ gti->coord_filter_enabled = of_property_read_bool(np, "goog,coord-filter-enabled");
}
/* Initialize default functions. */
gti->options.get_context_driver = goog_get_context_driver_nop;
gti->options.get_context_stylus = goog_get_context_stylus_nop;
+ gti->options.get_coord_filter_enabled = goog_get_coord_filter_enabled_nop;
gti->options.get_fw_version = goog_get_fw_version_nop;
gti->options.get_grip_mode = goog_get_grip_mode_nop;
gti->options.get_irq_mode = goog_get_irq_mode_nop;
@@ -2979,10 +2896,12 @@ void goog_init_options(struct goog_touch_interface *gti,
gti->options.reset = goog_reset_nop;
gti->options.selftest = goog_selftest_nop;
gti->options.set_continuous_report = goog_set_continuous_report_nop;
+ gti->options.set_coord_filter_enabled = goog_set_coord_filter_enabled_nop;
gti->options.set_grip_mode = goog_set_grip_mode_nop;
gti->options.set_heatmap_enabled = goog_set_heatmap_enabled_nop;
gti->options.set_irq_mode = goog_set_irq_mode_nop;
gti->options.set_palm_mode = goog_set_palm_mode_nop;
+ gti->options.set_report_rate = goog_set_report_rate_nop;
gti->options.set_scan_mode = goog_set_scan_mode_nop;
gti->options.set_screen_protector_mode = goog_set_screen_protector_mode_nop;
gti->options.set_sensing_mode = goog_set_sensing_mode_nop;
@@ -2993,6 +2912,8 @@ void goog_init_options(struct goog_touch_interface *gti,
gti->options.get_context_driver = options->get_context_driver;
if (options->get_context_stylus)
gti->options.get_context_stylus = options->get_context_stylus;
+ if (options->get_coord_filter_enabled)
+ gti->options.get_coord_filter_enabled = options->get_coord_filter_enabled;
if (options->get_fw_version)
gti->options.get_fw_version = options->get_fw_version;
if (options->get_grip_mode)
@@ -3025,6 +2946,8 @@ void goog_init_options(struct goog_touch_interface *gti,
gti->options.selftest = options->selftest;
if (options->set_continuous_report)
gti->options.set_continuous_report = options->set_continuous_report;
+ if (options->set_coord_filter_enabled)
+ gti->options.set_coord_filter_enabled = options->set_coord_filter_enabled;
if (options->set_grip_mode)
gti->options.set_grip_mode = options->set_grip_mode;
if (options->set_heatmap_enabled)
@@ -3033,6 +2956,8 @@ void goog_init_options(struct goog_touch_interface *gti,
gti->options.set_irq_mode = options->set_irq_mode;
if (options->set_palm_mode)
gti->options.set_palm_mode = options->set_palm_mode;
+ if (options->set_report_rate)
+ gti->options.set_report_rate = options->set_report_rate;
if (options->set_scan_mode)
gti->options.set_scan_mode = options->set_scan_mode;
if (options->set_screen_protector_mode)
@@ -3196,8 +3121,7 @@ static void goog_pm_suspend(struct gti_pm *pm)
gti_debug_hc_dump(gti);
gti_debug_input_dump(gti);
- if (gti->slot_bit_active)
- goog_input_release_all_fingers(gti);
+ goog_input_release_all_fingers(gti);
pm_relax(gti->dev);
}
@@ -3213,18 +3137,20 @@ static void goog_pm_resume(struct gti_pm *pm)
GOOG_WARN(gti, "GTI already resumed!\n");
return;
}
- pm->state = GTI_PM_RESUME;
pm_stay_awake(gti->dev);
if (gti->tbn_register_mask) {
- ret = tbn_request_bus(gti->tbn_register_mask);
+ gti->lptw_triggered = false;
+ ret = tbn_request_bus_with_result(gti->tbn_register_mask, &gti->lptw_triggered);
if (ret)
GOOG_ERR(gti, "tbn_request_bus failed, ret %d!\n", ret);
}
if (pm->resume)
pm->resume(gti->vendor_dev);
+
+ pm->state = GTI_PM_RESUME;
}
void goog_pm_state_update_work(struct work_struct *work) {
@@ -3291,15 +3217,28 @@ void goog_notify_fw_status_changed(struct goog_touch_interface *gti,
case GTI_FW_STATUS_GRIP_EXIT:
GOOG_INFO(gti, "Exit grip mode\n");
break;
+ case GTI_FW_STATUS_WATER_ENTER:
+ GOOG_INFO(gti, "Enter water mode\n");
+ gti->fw_status.water_mode = 1;
+ gti->context_changed.water_mode = 1;
+ break;
+ case GTI_FW_STATUS_WATER_EXIT:
+ GOOG_INFO(gti, "Exit water mode\n");
+ gti->fw_status.water_mode = 0;
+ gti->context_changed.water_mode = 1;
+ break;
case GTI_FW_STATUS_NOISE_MODE:
if (data == NULL) {
GOOG_INFO(gti, "Noise level is changed, level: unknown\n");
} else {
if (data->noise_level == GTI_NOISE_MODE_EXIT) {
GOOG_INFO(gti, "Exit noise mode\n");
+ gti->fw_status.noise_level= 0;
} else {
GOOG_INFO(gti, "Enter noise mode, level: %d\n", data->noise_level);
+ gti->fw_status.noise_level = data->noise_level;
}
+ gti->context_changed.noise_state = 1;
}
break;
default:
@@ -3330,8 +3269,6 @@ static int goog_pm_probe(struct goog_touch_interface *gti)
cpu_latency_qos_add_request(&gti->pm_qos_req, PM_QOS_DEFAULT_VALUE);
pm->enabled = true;
- return ret;
-
err_alloc_workqueue:
return ret;
}
@@ -3346,9 +3283,163 @@ static int goog_pm_remove(struct goog_touch_interface *gti)
if (pm->event_wq)
destroy_workqueue(pm->event_wq);
}
+
+ return 0;
+}
+
+static void goog_lookup_touch_report_rate(struct goog_touch_interface *gti)
+{
+ int i;
+ u32 next_report_rate = 0;
+
+ for (i = 0; i < gti->report_rate_table_size; i++) {
+ if (gti->display_vrefresh <= gti->display_refresh_rate_table[i]) {
+ next_report_rate = gti->touch_report_rate_table[i];
+ break;
+ }
+ }
+
+ /*
+ * Set the touch report as minimum value if the display_vrefresh is smaller
+ * than the minimum value of goog,display-vrr-table.
+ */
+ if (next_report_rate == 0)
+ next_report_rate = gti->touch_report_rate_table[0];
+
+ if (gti->report_rate_setting_next != next_report_rate) {
+ cancel_delayed_work_sync(&gti->set_report_rate_work);
+ gti->report_rate_setting_next = next_report_rate;
+ }
+
+ if (gti->report_rate_setting_next != gti->report_rate_setting &&
+ gti->pm.state == GTI_PM_RESUME) {
+ queue_delayed_work(gti->pm.event_wq, &gti->set_report_rate_work,
+ (gti->report_rate_setting_next > gti->report_rate_setting) ?
+ msecs_to_jiffies(gti->increase_report_rate_delay * MSEC_PER_SEC) :
+ msecs_to_jiffies(gti->decrease_report_rate_delay * MSEC_PER_SEC));
+ }
+}
+
+static void goog_set_report_rate_work(struct work_struct *work)
+{
+ int ret;
+ struct goog_touch_interface *gti;
+ struct delayed_work *delayed_work;
+ delayed_work = container_of(work, struct delayed_work, work);
+ gti = container_of(delayed_work, struct goog_touch_interface, set_report_rate_work);
+
+ if (gti->pm.state == GTI_PM_SUSPEND)
+ return;
+
+ if (gti->report_rate_setting == gti->report_rate_setting_next)
+ return;
+
+ /* Retry it 10ms later if there is finger on the screen. */
+ if (gti->slot_bit_active) {
+ queue_delayed_work(gti->pm.event_wq, &gti->set_report_rate_work,
+ msecs_to_jiffies(10));
+ return;
+ }
+
+ gti->cmd.report_rate_cmd.setting = gti->report_rate_setting_next;
+ ret = goog_process_vendor_cmd(gti, GTI_CMD_SET_REPORT_RATE);
+ if (ret != 0) {
+ GOOG_ERR(gti, "Failed to set report rate!\n");
+ return;
+ }
+
+ gti->report_rate_setting = gti->report_rate_setting_next;
+ gti->context_changed.touch_report_rate = 1;
+}
+
+static int goog_init_variable_report_rate(struct goog_touch_interface *gti)
+{
+ int table_size = 0;
+
+ if (!gti->pm.event_wq) {
+ GOOG_ERR(gti, "No workqueue for variable report rate.\n");
+ return -ENODEV;
+ }
+
+ gti->vrr_enabled = of_property_read_bool(gti->vendor_dev->of_node,
+ "goog,vrr-enabled");
+ if (!gti->vrr_enabled)
+ return 0;
+
+ table_size = of_property_count_u32_elems(gti->vendor_dev->of_node,
+ "goog,vrr-display-rate");
+ if (table_size != of_property_count_u32_elems(gti->vendor_dev->of_node,
+ "goog,vrr-touch-rate")) {
+ GOOG_ERR(gti, "Table size mismatch!\n");
+ goto init_variable_report_rate_failed;
+ }
+
+ gti->report_rate_table_size = table_size;
+
+ gti->display_refresh_rate_table = devm_kzalloc(gti->vendor_dev,
+ sizeof(u32) * table_size, GFP_KERNEL);
+ if (!gti->display_refresh_rate_table) {
+ GOOG_ERR(gti, "display_refresh_rate_table alloc failed.\n");
+ goto init_variable_report_rate_failed;
+ }
+
+ gti->touch_report_rate_table = devm_kzalloc(gti->vendor_dev,
+ sizeof(u32) * table_size, GFP_KERNEL);
+ if (!gti->touch_report_rate_table) {
+ GOOG_ERR(gti, "touch_report_rate_table alloc failed.\n");
+ goto init_variable_report_rate_failed;
+ }
+
+ if (of_property_read_u32_array(gti->vendor_dev->of_node, "goog,vrr-display-rate",
+ gti->display_refresh_rate_table, table_size)) {
+ GOOG_ERR(gti, "Failed to parse goog,display-vrr-table.\n");
+ goto init_variable_report_rate_failed;
+ }
+
+ if (of_property_read_u32_array(gti->vendor_dev->of_node, "goog,vrr-touch-rate",
+ gti->touch_report_rate_table, table_size)) {
+ GOOG_ERR(gti, "Failed to parse goog,touch-vrr-table.\n");
+ goto init_variable_report_rate_failed;
+ }
+
+ if (of_property_read_u32(gti->vendor_dev->of_node, "goog,vrr-up-delay",
+ &gti->increase_report_rate_delay)) {
+ gti->increase_report_rate_delay = 0;
+ }
+
+ if (of_property_read_u32(gti->vendor_dev->of_node, "goog,vrr-down-delay",
+ &gti->decrease_report_rate_delay)) {
+ gti->decrease_report_rate_delay = 0;
+ }
+
+ GOOG_INFO(gti, "Default report rate: %uHz, report rate delay %u/%u)",
+ gti->touch_report_rate_table[0],
+ gti->increase_report_rate_delay,
+ gti->decrease_report_rate_delay);
+
+ gti->report_rate_setting = gti->touch_report_rate_table[0];
+ gti->report_rate_setting_next = gti->touch_report_rate_table[0];
+ INIT_DELAYED_WORK(&gti->set_report_rate_work, goog_set_report_rate_work);
+
+ return 0;
+
+init_variable_report_rate_failed:
+ gti->vrr_enabled = false;
+ devm_kfree(gti->vendor_dev, gti->display_refresh_rate_table);
+ devm_kfree(gti->vendor_dev, gti->touch_report_rate_table);
+
return 0;
}
+int goog_get_lptw_triggered(struct goog_touch_interface *gti)
+{
+ if (gti == NULL)
+ return -ENODEV;
+
+ return gti->lptw_triggered;
+}
+EXPORT_SYMBOL(goog_get_lptw_triggered);
+
static irqreturn_t gti_irq_handler(int irq, void *data)
{
irqreturn_t ret;
@@ -3370,13 +3461,21 @@ static irqreturn_t gti_irq_thread_fn(int irq, void *data)
ATRACE_BEGIN(__func__);
cpu_latency_qos_update_request(&gti->pm_qos_req, 100 /* usec */);
+
+ /*
+ * Some vendor drivers read sensor data inside vendor_irq_thread_fn.
+ * We need to lock input_process_lock before vendor_irq_thread_fn to
+ * avoid thread safe issue.
+ */
+ mutex_lock(&gti->input_process_lock);
+
if (gti->vendor_irq_thread_fn)
ret = gti->vendor_irq_thread_fn(irq, gti->vendor_irq_cookie);
else
ret = IRQ_HANDLED;
- mutex_lock(&gti->input_process_lock);
- goog_input_process(gti, true);
+ goog_input_process(gti, false);
+
mutex_unlock(&gti->input_process_lock);
gti_debug_hc_update(gti, false);
@@ -3457,9 +3556,6 @@ struct goog_touch_interface *goog_touch_interface_probe(
gti->vendor_dev = dev;
gti->vendor_input_dev = input_dev;
gti->vendor_default_handler = default_handler;
- gti->mf_mode = GTI_MF_MODE_DEFAULT;
- gti->screen_protector_mode_setting = GTI_SCREEN_PROTECTOR_MODE_DISABLE;
- gti->display_state = GTI_DISPLAY_STATE_ON;
mutex_init(&gti->input_lock);
mutex_init(&gti->input_process_lock);
}
@@ -3468,7 +3564,15 @@ struct goog_touch_interface *goog_touch_interface_probe(
gti_class = class_create(THIS_MODULE, GTI_NAME);
if (gti && gti_class) {
- char *name = kasprintf(GFP_KERNEL, "gti.%d", gti_dev_num);
+ u32 dev_id = gti_dev_num;
+ char *name;
+
+ if (gti->vendor_dev) {
+ struct device_node *np = gti->vendor_dev->of_node;
+
+ of_property_read_u32(np, "goog,dev-id", &dev_id);
+ }
+ name = kasprintf(GFP_KERNEL, "gti.%d", dev_id);
if (name &&
!alloc_chrdev_region(&gti->dev_id, 0, 1, name)) {
@@ -3506,10 +3610,11 @@ struct goog_touch_interface *goog_touch_interface_probe(
* goog_init_input() needs the offload.cap initialization by goog_offload_probe().
*/
goog_init_input(gti);
- goog_update_fw_settings(gti);
goog_register_tbn(gti);
goog_pm_probe(gti);
register_panel_bridge(gti);
+ goog_init_variable_report_rate(gti);
+ goog_update_fw_settings(gti);
ret = sysfs_create_group(&gti->dev->kobj, &goog_attr_group);
if (ret)
diff --git a/goog_touch_interface.h b/goog_touch_interface.h
index 7321e47..9145538 100644
--- a/goog_touch_interface.h
+++ b/goog_touch_interface.h
@@ -49,6 +49,7 @@ enum gti_cmd_type : u32 {
GTI_CMD_GET_OPS_START = 0x200,
GTI_CMD_GET_CONTEXT_DRIVER,
GTI_CMD_GET_CONTEXT_STYLUS,
+ GTI_CMD_GET_COORD_FILTER_ENABLED,
GTI_CMD_GET_FW_VERSION,
GTI_CMD_GET_GRIP_MODE,
GTI_CMD_GET_IRQ_MODE,
@@ -67,10 +68,12 @@ enum gti_cmd_type : u32 {
/* GTI_CMD_SET operations. */
GTI_CMD_SET_OPS_START = 0x400,
GTI_CMD_SET_CONTINUOUS_REPORT,
+ GTI_CMD_SET_COORD_FILTER_ENABLED,
GTI_CMD_SET_GRIP_MODE,
GTI_CMD_SET_HEATMAP_ENABLED,
GTI_CMD_SET_IRQ_MODE,
GTI_CMD_SET_PALM_MODE,
+ GTI_CMD_SET_REPORT_RATE,
GTI_CMD_SET_SCAN_MODE,
GTI_CMD_SET_SCREEN_PROTECTOR_MODE,
GTI_CMD_SET_SENSING_MODE,
@@ -82,6 +85,11 @@ enum gti_continuous_report_setting : u32 {
GTI_CONTINUOUS_REPORT_DRIVER_DEFAULT,
};
+enum gti_coord_filter_setting : u32 {
+ GTI_COORD_FILTER_DISABLE = 0,
+ GTI_COORD_FILTER_ENABLE,
+};
+
enum gti_display_state_setting : u32 {
GTI_DISPLAY_STATE_OFF = 0,
GTI_DISPLAY_STATE_ON,
@@ -143,8 +151,8 @@ enum gti_ping_mode : u32 {
};
enum gti_pm_state : u32 {
- GTI_PM_RESUME = 0,
- GTI_PM_SUSPEND,
+ GTI_PM_SUSPEND = 0,
+ GTI_PM_RESUME,
};
#define GTI_PM_WAKELOCK_TYPE_LOCK_MASK 0xFFFF
@@ -159,6 +167,7 @@ enum gti_pm_wakelock_type : u32 {
GTI_PM_WAKELOCK_TYPE_FORCE_ACTIVE = (1 << 4),
GTI_PM_WAKELOCK_TYPE_BUGREPORT = (1 << 5),
GTI_PM_WAKELOCK_TYPE_OFFLOAD_REPORT = (1 << 6),
+ GTI_PM_WAKELOCK_TYPE_SENSOR_DATA = (1 << 7),
};
enum gti_proc_type : u32 {
@@ -231,17 +240,14 @@ enum gti_sensor_data_type : u32 {
TOUCH_SCAN_TYPE_SELF | TOUCH_DATA_TYPE_BASELINE,
};
-enum gti_vendor_dev_pm_state : u32 {
- GTI_VENDOR_DEV_RESUME = 0,
- GTI_VENDOR_DEV_SUSPEND,
-};
-
enum gti_fw_status : u32 {
GTI_FW_STATUS_RESET = 0,
GTI_FW_STATUS_PALM_ENTER,
GTI_FW_STATUS_PALM_EXIT,
GTI_FW_STATUS_GRIP_ENTER,
GTI_FW_STATUS_GRIP_EXIT,
+ GTI_FW_STATUS_WATER_ENTER,
+ GTI_FW_STATUS_WATER_EXIT,
GTI_FW_STATUS_NOISE_MODE,
};
@@ -256,8 +262,9 @@ enum gti_noise_mode_level : u8 {
* Structures.
*/
-struct gti_context_driver_cmd {
- struct {
+struct gti_context_changed {
+ union {
+ struct {
u32 screen_state : 1;
u32 display_refresh_rate : 1;
u32 touch_report_rate : 1;
@@ -266,7 +273,13 @@ struct gti_context_driver_cmd {
u32 charger_state : 1;
u32 hinge_angle : 1;
u32 offload_timestamp : 1;
- } contents;
+ };
+ u32 value;
+ };
+};
+
+struct gti_context_driver_cmd {
+ struct gti_context_changed context_changed;
u8 screen_state;
u8 display_refresh_rate;
@@ -315,6 +328,10 @@ struct gti_debug_input {
struct gti_debug_coord released;
};
+struct gti_coord_filter_cmd {
+ enum gti_coord_filter_setting setting;
+};
+
struct gti_display_state_cmd {
enum gti_display_state_setting setting;
};
@@ -347,6 +364,10 @@ struct gti_ping_cmd {
enum gti_ping_mode setting;
};
+struct gti_report_rate_cmd {
+ u32 setting;
+};
+
struct gti_reset_cmd {
enum gti_reset_mode setting;
};
@@ -379,6 +400,7 @@ struct gti_sensor_data_cmd {
* @context_driver_cmd: command to update touch offload driver context.
* @context_stylus_cmd: command to update touch offload stylus context.
* @continuous_report_cmd: command to set continuous reporting.
+ * @coord_filter_cmd: command to set/get coordinate filter enabled.
* @display_state_cmd: command to notify display state.
* @display_vrefresh_cmd: command to notify display vertical refresh rate.
* @fw_version_cmd: command to get fw version.
@@ -387,6 +409,7 @@ struct gti_sensor_data_cmd {
* @irq_cmd: command to set/get irq mode.
* @palm_cmd: command to set/get palm mode.
* @ping_cmd: command to ping T-IC.
+ * @report_rate_cmd: command to change touch report rate.
* @reset_cmd: command to reset T-IC.
* @scan_cmd: command to set/get scan mode.
* @screen_protector_mode_cmd: command to set/get screen protector mode.
@@ -399,6 +422,7 @@ struct gti_union_cmd_data {
struct gti_context_driver_cmd context_driver_cmd;
struct gti_context_stylus_cmd context_stylus_cmd;
struct gti_continuous_report_cmd continuous_report_cmd;
+ struct gti_coord_filter_cmd coord_filter_cmd;
struct gti_display_state_cmd display_state_cmd;
struct gti_display_vrefresh_cmd display_vrefresh_cmd;
struct gti_fw_version_cmd fw_version_cmd;
@@ -407,6 +431,7 @@ struct gti_union_cmd_data {
struct gti_irq_cmd irq_cmd;
struct gti_palm_cmd palm_cmd;
struct gti_ping_cmd ping_cmd;
+ struct gti_report_rate_cmd report_rate_cmd;
struct gti_reset_cmd reset_cmd;
struct gti_scan_cmd scan_cmd;
struct gti_screen_protector_mode_cmd screen_protector_mode_cmd;
@@ -422,12 +447,14 @@ struct gti_union_cmd_data {
*/
struct gti_fw_status_data {
enum gti_noise_mode_level noise_level;
+ u8 water_mode;
};
/**
* struct gti_optional_configuration - optional configuration by vendor driver.
* @get_context_driver: vendor driver operation to update touch offload driver context.
* @get_context_stylus: vendor driver operation to update touch offload stylus context.
+ * @get_coord_filter_enabled: vendor driver operation to get the coordinate filter enabled.
* @get_fw_version: vendor driver operation to get fw version info.
* @get_grip_mode: vendor driver operation to get the grip mode setting.
* @get_irq_mode: vendor driver operation to get irq mode setting.
@@ -443,10 +470,12 @@ struct gti_fw_status_data {
* @reset: vendor driver operation to exec reset.
* @selftest: vendor driver operation to exec self-test.
* @set_continuous_report: vendor driver operation to apply the continuous reporting setting.
+ * @set_coord_filter_enabled: vendor driver operation to apply the coordinate filter enabled.
* @set_grip_mode: vendor driver operation to apply the grip setting.
* @set_heatmap_enabled: vendor driver operation to apply the heatmap setting.
* @set_irq_mode: vendor driver operation to apply the irq setting.
* @set_palm_mode: vendor driver operation to apply the palm setting.
+ * @set_report_rate: driver operation to set touch report rate.
* @set_scan_mode: vendor driver operation to set scan mode.
* @set_screen_protector_mode: vendor driver operation to set screen protector mode.
* @set_sensing_mode: vendor driver operation to set sensing mode.
@@ -454,13 +483,15 @@ struct gti_fw_status_data {
struct gti_optional_configuration {
int (*get_context_driver)(void *private_data, struct gti_context_driver_cmd *cmd);
int (*get_context_stylus)(void *private_data, struct gti_context_stylus_cmd *cmd);
+ int (*get_coord_filter_enabled)(void *private_data, struct gti_coord_filter_cmd *cmd);
int (*get_fw_version)(void *private_data, struct gti_fw_version_cmd *cmd);
int (*get_grip_mode)(void *private_data, struct gti_grip_cmd *cmd);
int (*get_irq_mode)(void *private_data, struct gti_irq_cmd *cmd);
int (*get_mutual_sensor_data)(void *private_data, struct gti_sensor_data_cmd *cmd);
int (*get_palm_mode)(void *private_data, struct gti_palm_cmd *cmd);
int (*get_scan_mode)(void *private_data, struct gti_scan_cmd *cmd);
- int (*get_screen_protector_mode)(void *private_data, struct gti_screen_protector_mode_cmd *cmd);
+ int (*get_screen_protector_mode)(void *private_data,
+ struct gti_screen_protector_mode_cmd *cmd);
int (*get_self_sensor_data)(void *private_data, struct gti_sensor_data_cmd *cmd);
int (*get_sensing_mode)(void *private_data, struct gti_sensing_cmd *cmd);
int (*notify_display_state)(void *private_data, struct gti_display_state_cmd *cmd);
@@ -469,12 +500,15 @@ struct gti_optional_configuration {
int (*reset)(void *private_data, struct gti_reset_cmd *cmd);
int (*selftest)(void *private_data, struct gti_selftest_cmd *cmd);
int (*set_continuous_report)(void *private_data, struct gti_continuous_report_cmd *cmd);
+ int (*set_coord_filter_enabled)(void *private_data, struct gti_coord_filter_cmd *cmd);
int (*set_grip_mode)(void *private_data, struct gti_grip_cmd *cmd);
int (*set_heatmap_enabled)(void *private_data, struct gti_heatmap_cmd *cmd);
int (*set_irq_mode)(void *private_data, struct gti_irq_cmd *cmd);
int (*set_palm_mode)(void *private_data, struct gti_palm_cmd *cmd);
+ int (*set_report_rate)(void *private_data, struct gti_report_rate_cmd *cmd);
int (*set_scan_mode)(void *private_data, struct gti_scan_cmd *cmd);
- int (*set_screen_protector_mode)(void *private_data, struct gti_screen_protector_mode_cmd *cmd);
+ int (*set_screen_protector_mode)(void *private_data,
+ struct gti_screen_protector_mode_cmd *cmd);
int (*set_sensing_mode)(void *private_data, struct gti_sensing_cmd *cmd);
};
@@ -528,21 +562,36 @@ struct gti_pm {
* @display_vrefresh: display vrefresh in Hz.
* @mf_mode: current motion filter mode.
* @mf_state: current motion filter state.
+ * @vrr_enabled: variable touch report rate is enabled or not.
+ * @report_rate_table_size: report rate table size from device tree.
+ * @touch_report_rate_table: touch report rate table parsed from device tree.
+ * @display_refresh_rate_table: display refresh rate table parsed from device tree.
+ * @report_rate_setting: current touch report rate.
+ * @report_rate_setting_next: next touch report rate going be set.
+ * @set_report_rate_work: delayed work for setting report rate.
+ * @increase_report_rate_delay: delayed work will be start after a delay in seconds.
+ * @decrease_report_rate_delay: delayed work will be start after a delay in seconds.
* @screen_protector_mode_setting: the setting of screen protector mode.
* @tbn_register_mask: the tbn_mask that used to request/release touch bus.
* @pm: struct that used by gti pm.
* @pm_qos_req: struct that used by pm qos.
+ * @fw_status: firmware status such as water_mode, noise_level, etc.
+ * @context_changed: flags that indicate driver status changing.
* @panel_is_lp_mode: display is in low power mode.
- * @offload_enable: touch offload is enabled or not.
- * @v4l2_enable: v4l2 is enabled or not.
- * @tbn_enable: tbn is enabled or not.
+ * @offload_enabled: touch offload is enabled or not.
+ * @v4l2_enabled: v4l2 is enabled or not.
+ * @tbn_enabled: tbn is enabled or not.
+ * @coord_filter_enabled: coordinate filter is enabled or not.
* @input_timestamp_changed: input timestamp changed from touch vendor driver.
* @ignore_grip_update: Ignore fw_grip status updates made on offload state change.
* @default_grip_enabled: the grip default setting.
* @ignore_palm_update: Ignore fw_palm status updates made on offload state change.
* @default_palm_enabled: the palm default setting.
+ * @ignore_coord_filter_update: Ignore fw_coordinate_filter status updates.
+ * @fw_coord_filter_enabled: the current setting of coordinate filter.
+ * @default_coord_filter_enabled: the default setting of coordinate filter.
+ * @lptw_triggered: LPTW is triggered or not.
* @ignore_force_active: Ignore the force_active sysfs request.
- * @ignore_screenoff_heatmap: Ignore the heatmap request during screen-off.
* @offload_id: id that used by touch offload.
* @heatmap_buf: heatmap buffer that used by v4l2.
* @heatmap_buf_size: heatmap buffer size that used by v4l2.
@@ -551,6 +600,8 @@ struct gti_pm {
* @slot_bit_changed: bitmap of slot state changed for this input process cycle.
* @slot_bit_active: bitmap of active slot during GTI lifecycle.
* @dev_id: dev_t used for google interface driver.
+ * @charger_state: indicates a USB charger is connected.
+ * @charger_notifier: notifier for power_supply updates.
* @irq_index: irq count that handle by GTI.
* @input_index: the count of slot bit changed during goog_input_process().
* @vendor_irq_handler: irq handler that register by vendor driver.
@@ -583,6 +634,16 @@ struct goog_touch_interface {
ktime_t input_timestamp;
ktime_t mf_downtime;
+ bool vrr_enabled;
+ int report_rate_table_size;
+ u32 *display_refresh_rate_table;
+ u32 *touch_report_rate_table;
+ u32 report_rate_setting;
+ u32 report_rate_setting_next;
+ struct delayed_work set_report_rate_work;
+ u32 increase_report_rate_delay;
+ u32 decrease_report_rate_delay;
+
int display_vrefresh;
enum gti_display_state_setting display_state;
enum gti_mf_mode mf_mode;
@@ -592,18 +653,24 @@ struct goog_touch_interface {
struct gti_pm pm;
struct pm_qos_request pm_qos_req;
+ struct gti_fw_status_data fw_status;
+ struct gti_context_changed context_changed;
+
bool panel_is_lp_mode;
bool offload_enabled;
bool v4l2_enabled;
bool tbn_enabled;
+ bool coord_filter_enabled;
bool input_timestamp_changed;
bool ignore_grip_update;
bool default_grip_enabled;
bool ignore_palm_update;
bool default_palm_enabled;
+ bool ignore_coord_filter_update;
+ bool fw_coord_filter_enabled;
+ bool default_coord_filter_enabled;
+ bool lptw_triggered;
bool ignore_force_active;
- bool ignore_screenoff_heatmap;
- unsigned int wakeup_before_force_active_delay;
union {
u8 offload_id_byte[4];
u32 offload_id;
@@ -616,6 +683,9 @@ struct goog_touch_interface {
unsigned long slot_bit_active;
dev_t dev_id;
+ u8 charger_state;
+ struct notifier_block charger_notifier;
+
u64 irq_index;
u64 input_index;
irq_handler_t vendor_irq_handler;
@@ -666,7 +736,7 @@ inline int goog_request_threaded_irq(struct goog_touch_interface *gti,
unsigned long irqflags, const char *devname, void *dev_id);
int goog_process_vendor_cmd(struct goog_touch_interface *gti, enum gti_cmd_type cmd_type);
-int goog_input_process(struct goog_touch_interface *gti, bool report_from_irq);
+int goog_input_process(struct goog_touch_interface *gti, bool reset_data);
struct goog_touch_interface *goog_touch_interface_probe(
void *private_data,
struct device *dev,
@@ -696,5 +766,7 @@ void goog_notify_fw_status_changed(struct goog_touch_interface *gti,
void gti_debug_hc_dump(struct goog_touch_interface *gti);
void gti_debug_input_dump(struct goog_touch_interface *gti);
+int goog_get_lptw_triggered(struct goog_touch_interface *gti);
+
#endif // _GOOG_TOUCH_INTERFACE_
diff --git a/include/uapi/input/touch_offload.h b/include/uapi/input/touch_offload.h
index 4a10ba1..eb8af30 100644
--- a/include/uapi/input/touch_offload.h
+++ b/include/uapi/input/touch_offload.h
@@ -61,6 +61,7 @@
* filter_palm - driver supports disabling underlying palm rejection
* num_sensitivity_settings - number of sensitivity options provided
* auto_reporting - report heatmap when screen is not touched
+ * coord_filter - driver supports disabling underlying coordinate filter
*/
struct TouchOffloadCaps {
/* Version info */
@@ -95,7 +96,8 @@ struct TouchOffloadCaps {
__u8 filter_palm;
__u8 num_sensitivity_settings;
__u8 auto_reporting;
- __u8 reserved4[32];
+ __u8 coord_filter;
+ __u8 reserved4[31];
} __attribute__((packed));
/* TouchOffloadConfig
@@ -107,6 +109,7 @@ struct TouchOffloadCaps {
* filter_palm - enable underlying palm rejection
* sensitivity_setting - selected sensitivity
* auto_reporting - enable reporting when screen is not touched
+ * coord_filter - enable underlying coordinate filter
* read_coords - allocate a channel to coordinate data
* mutual_data_types - bitfield of mutual data types to collect
* self_data_types - bitfield of self data types to collect
@@ -122,7 +125,8 @@ struct TouchOffloadConfig {
__u8 filter_palm;
__u8 sensitivity_setting;
__u8 auto_reporting;
- __u8 reserved1[16];
+ __u8 coord_filter;
+ __u8 reserved1[15];
/* Data to read */
__u8 read_coords;
diff --git a/touch_bus_negotiator.c b/touch_bus_negotiator.c
index 94d7134..51898a0 100644
--- a/touch_bus_negotiator.c
+++ b/touch_bus_negotiator.c
@@ -17,20 +17,26 @@
#include <linux/delay.h>
#include "touch_bus_negotiator.h"
+#if IS_ENABLED(CONFIG_TOUCHSCREEN_TBN_AOC_CHANNEL_MODE)
+#include <uapi/linux/sched/types.h>
+#include "aoc_tbn_service_dev.h"
+#endif
+
#define TBN_MODULE_NAME "touch_bus_negotiator"
+#define TBN_AOC_CHANNEL_THREAD_NAME "tbn_aoc_channel"
-static struct tbn_context *tbn_context = NULL;
+#if IS_ENABLED(CONFIG_TOUCHSCREEN_TBN_AOC_CHANNEL_MODE)
+static void handle_tbn_event_response(struct tbn_context *tbn,
+ struct TbnEventResponse *response);
+#endif
-enum tbn_operation {
- AP_RELEASE_BUS,
- AP_REQUEST_BUS,
-};
+static struct tbn_context *tbn_context;
static irqreturn_t tbn_aoc2ap_irq_thread(int irq, void *ptr)
{
struct tbn_context *tbn = ptr;
- dev_info(tbn_context->dev, "%s: bus_released:%d bus_requested:%d.\n", __func__,
+ dev_info(tbn->dev, "%s: bus_released:%d bus_requested:%d.\n", __func__,
completion_done(&tbn->bus_released), completion_done(&tbn->bus_requested));
if (completion_done(&tbn->bus_released) && completion_done(&tbn->bus_requested))
@@ -65,7 +71,113 @@ static irqreturn_t tbn_aoc2ap_irq_thread(int irq, void *ptr)
return IRQ_HANDLED;
}
-int tbn_handshaking(struct tbn_context *tbn, enum tbn_operation operation)
+#if IS_ENABLED(CONFIG_TOUCHSCREEN_TBN_AOC_CHANNEL_MODE)
+static int aoc_channel_kthread(void *data)
+{
+ struct tbn_context *tbn = data;
+ struct TbnEventResponse resp;
+ ssize_t len;
+ bool service_ready = false;
+
+ while (!kthread_should_stop()) {
+ if (service_ready != aoc_tbn_service_ready()) {
+ service_ready = !service_ready;
+ dev_info(tbn->dev, "%s: AOC TBN service is %s.\n",
+ __func__, service_ready ? "ready" : "not ready");
+ }
+
+ if (!service_ready) {
+ msleep(1000);
+ continue;
+ }
+
+ len = aoc_tbn_service_read(&resp, sizeof(resp));
+ if (len < 0) {
+ dev_err(tbn->dev, "%s: failed to read message, err: %d\n",
+ __func__, len);
+ msleep(1000);
+ continue;
+ }
+
+ if (kthread_should_stop()) {
+ break;
+ }
+
+ if (len == sizeof(resp)) {
+ handle_tbn_event_response(tbn, &resp);
+ }
+ }
+
+ return 0;
+}
+
+static void handle_tbn_event_response(struct tbn_context *tbn,
+ struct TbnEventResponse *response)
+{
+ mutex_lock(&tbn->event_lock);
+
+ if (response->id != tbn->event.id) {
+ dev_err(tbn->dev,
+ "%s: receive wrong response, id: %d, expected id: %d, "
+ "bus_released:%d bus_requested:%d.\n",
+ __func__, response->id, tbn->event.id,
+ completion_done(&tbn->bus_released),
+ completion_done(&tbn->bus_requested));
+ goto exit;
+ }
+
+ if (response->err != 0) {
+ dev_err(tbn->dev, "%s: send tbn event failed, err %d!\n",
+ __func__, response->err);
+ tbn->event_resp.err = response->err;
+ } else {
+ tbn->event_resp.lptw_triggered = response->lptw_triggered;
+ }
+
+ if (response->operation == TBN_OPERATION_AP_REQUEST_BUS) {
+ complete_all(&tbn->bus_requested);
+ } else if (response->operation == TBN_OPERATION_AP_RELEASE_BUS) {
+ complete_all(&tbn->bus_released);
+ } else {
+ dev_err(tbn->dev, "%s: response unknown operation, op: %d!\n",
+ __func__, response->operation);
+ }
+
+exit:
+ mutex_unlock(&tbn->event_lock);
+}
+
+static void send_tbn_event(struct tbn_context *tbn, enum TbnOperation operation)
+{
+ ssize_t len;
+ int retry = 3;
+
+ if (!aoc_tbn_service_ready()) {
+ dev_err(tbn_context->dev, "%s: AOC TBN service is not ready.\n",
+ __func__);
+ return;
+ }
+
+ mutex_lock(&tbn->event_lock);
+
+ tbn->event.operation = operation;
+ tbn->event.id++;
+
+ while (retry) {
+ len = aoc_tbn_service_write(&tbn->event, sizeof(tbn->event));
+ if (len == sizeof(tbn->event)) {
+ break;
+ }
+ dev_err(tbn_context->dev, "%s: failed to send TBN event, retry: %d.\n",
+ __func__, retry);
+ retry--;
+ }
+
+ mutex_unlock(&tbn->event_lock);
+}
+#endif
+
+int tbn_handshaking(struct tbn_context *tbn, enum TbnOperation operation)
{
struct completion *wait_for_completion;
enum tbn_bus_owner bus_owner;
@@ -74,29 +186,35 @@ int tbn_handshaking(struct tbn_context *tbn, enum tbn_operation operation)
const char *msg;
int ret = 0;
- if (!tbn || tbn->registered_mask == 0)
- return 0;
+ if (!tbn || tbn->registered_mask == 0) {
+ dev_err(tbn_context->dev, "%s: tbn is not ready to serve.\n", __func__);
+ return -EINVAL;
+ }
- if (operation == AP_REQUEST_BUS) {
+ if (operation == TBN_OPERATION_AP_REQUEST_BUS) {
wait_for_completion = &tbn->bus_requested;
bus_owner = TBN_BUS_OWNER_AP;
irq_type = IRQF_TRIGGER_FALLING;
timeout = TBN_REQUEST_BUS_TIMEOUT_MS;
msg = "request";
- } else {
+ } else if (operation == TBN_OPERATION_AP_RELEASE_BUS) {
wait_for_completion = &tbn->bus_released;
bus_owner = TBN_BUS_OWNER_AOC;
irq_type = IRQF_TRIGGER_RISING;
timeout = TBN_RELEASE_BUS_TIMEOUT_MS;
msg = "release";
+ } else {
+ dev_err(tbn_context->dev, "%s: request unknown operation, op: %d.\n",
+ __func__, operation);
+ return -EINVAL;
}
- reinit_completion(wait_for_completion);
-
if (tbn->mode == TBN_MODE_GPIO) {
int ap2aoc_val_org = gpio_get_value(tbn->ap2aoc_gpio);
int aoc2ap_val_org = gpio_get_value(tbn->aoc2ap_gpio);
+ reinit_completion(wait_for_completion);
+
irq_set_irq_type(tbn->aoc2ap_irq, irq_type);
enable_irq(tbn->aoc2ap_irq);
gpio_direction_output(tbn->ap2aoc_gpio, bus_owner);
@@ -117,12 +235,38 @@ int tbn_handshaking(struct tbn_context *tbn, enum tbn_operation operation)
} else
dev_info(tbn->dev, "AP %s bus ... SUCCESS!\n", msg);
disable_irq_nosync(tbn->aoc2ap_irq);
+#if IS_ENABLED(CONFIG_TOUCHSCREEN_TBN_AOC_CHANNEL_MODE)
+ } else if (tbn->mode == TBN_MODE_AOC_CHANNEL) {
+ tbn->event_resp.lptw_triggered = false;
+ tbn->event_resp.err = 0;
+
+ reinit_completion(wait_for_completion);
+
+ send_tbn_event(tbn, operation);
+ if (wait_for_completion_timeout(wait_for_completion,
+ msecs_to_jiffies(timeout)) == 0) {
+ dev_err(tbn->dev, "AP %s bus ... timeout!\n", msg);
+ complete_all(wait_for_completion);
+ ret = -ETIMEDOUT;
+ } else {
+ if (tbn->event_resp.err == 0) {
+ dev_info(tbn->dev, "AP %s bus ... SUCCESS!\n", msg);
+ } else {
+ dev_info(tbn->dev, "AP %s bus ... failed!\n", msg);
+ ret = -EBUSY;
+ }
+ }
+#endif
+ } else if (tbn->mode == TBN_MODE_MOCK) {
+ dev_info(tbn->dev, "AP %s bus ... SUCCESS!\n", msg);
+ } else {
+ ret = -EINVAL;
}
return ret;
}
-int tbn_request_bus(u32 dev_mask)
+int tbn_request_bus_with_result(u32 dev_mask, bool *lptw_triggered)
{
int ret = 0;
@@ -139,11 +283,13 @@ int tbn_request_bus(u32 dev_mask)
}
if (tbn_context->requested_dev_mask == 0) {
- ret = tbn_handshaking(tbn_context, AP_REQUEST_BUS);
+ ret = tbn_handshaking(tbn_context, TBN_OPERATION_AP_REQUEST_BUS);
+ if ((ret == 0) && (lptw_triggered != NULL))
+ *lptw_triggered = tbn_context->event_resp.lptw_triggered;
} else {
dev_dbg(tbn_context->dev,
- "%s: Bus already requested, requested_dev_mask %#x dev_mask %#x.\n",
- __func__, tbn_context->requested_dev_mask, dev_mask);
+ "%s: Bus already requested, requested_dev_mask %#x dev_mask %#x.\n",
+ __func__, tbn_context->requested_dev_mask, dev_mask);
}
tbn_context->requested_dev_mask |= dev_mask;
@@ -151,6 +297,12 @@ int tbn_request_bus(u32 dev_mask)
return ret;
}
+EXPORT_SYMBOL_GPL(tbn_request_bus_with_result);
+
+int tbn_request_bus(u32 dev_mask)
+{
+ return tbn_request_bus_with_result(dev_mask, NULL);
+}
EXPORT_SYMBOL_GPL(tbn_request_bus);
int tbn_release_bus(u32 dev_mask)
@@ -179,7 +331,7 @@ int tbn_release_bus(u32 dev_mask)
/* Release the bus when the last requested_dev_mask bit releases. */
if (tbn_context->requested_dev_mask == dev_mask) {
- ret = tbn_handshaking(tbn_context, AP_RELEASE_BUS);
+ ret = tbn_handshaking(tbn_context, TBN_OPERATION_AP_RELEASE_BUS);
} else {
dev_dbg(tbn_context->dev,
"%s: Bus is still in use, requested_dev_mask %#x dev_mask %#x.\n",
@@ -198,6 +350,8 @@ int register_tbn(u32 *output)
{
u32 i = 0;
+ *output = 0;
+
if (!tbn_context) {
pr_warn("%s: tbn_context doesn't exist.", __func__);
return 0;
@@ -238,22 +392,30 @@ static int tbn_probe(struct platform_device *pdev)
struct tbn_context *tbn = NULL;
struct device_node *np = dev->of_node;
int err = 0;
+#if IS_ENABLED(CONFIG_TOUCHSCREEN_TBN_AOC_CHANNEL_MODE)
+ struct sched_param param = {
+ .sched_priority = 10,
+ };
+#endif
+
tbn = devm_kzalloc(dev, sizeof(struct tbn_context), GFP_KERNEL);
if (!tbn)
goto failed;
tbn->dev = dev;
+ tbn->event_resp.lptw_triggered = false;
tbn_context = tbn;
dev_set_drvdata(tbn->dev, tbn);
if (of_property_read_u32(np, "tbn,max_devices", &tbn->max_devices))
tbn->max_devices = 1;
- if (of_property_read_bool(np, "tbn,ap2aoc_gpio") &&
- of_property_read_bool(np, "tbn,aoc2ap_gpio")) {
+ err = of_property_read_u32(np, "tbn,mode", &tbn->mode);
+ if (err)
tbn->mode = TBN_MODE_GPIO;
+ if (tbn->mode == TBN_MODE_GPIO) {
tbn->ap2aoc_gpio = of_get_named_gpio(np, "tbn,ap2aoc_gpio", 0);
if (gpio_is_valid(tbn->ap2aoc_gpio)) {
err = devm_gpio_request_one(tbn->dev, tbn->ap2aoc_gpio,
@@ -298,8 +460,32 @@ static int tbn_probe(struct platform_device *pdev)
err = -EPROBE_DEFER;
goto failed;
}
+
+ dev_info(tbn->dev,
+ "%s: gpios(aoc2ap: %d ap2aoc: %d)\n",
+ __func__, tbn->aoc2ap_gpio, tbn->ap2aoc_gpio);
+#if IS_ENABLED(CONFIG_TOUCHSCREEN_TBN_AOC_CHANNEL_MODE)
+ } else if (tbn->mode == TBN_MODE_AOC_CHANNEL) {
+ mutex_init(&tbn->event_lock);
+
+ tbn->aoc_channel_task = kthread_run(&aoc_channel_kthread, tbn,
+ TBN_AOC_CHANNEL_THREAD_NAME);
+ if (IS_ERR(tbn->aoc_channel_task)) {
+ err = PTR_ERR(tbn->aoc_channel_task);
+ goto failed;
+ }
+
+ err = sched_setscheduler(tbn->aoc_channel_task, SCHED_FIFO, &param);
+ if (err != 0) {
+ goto failed;
+ }
+#endif
+ } else if (tbn->mode == TBN_MODE_MOCK) {
+ err = 0;
} else {
- tbn->mode = TBN_MODE_DISABLED;
+ dev_err(tbn->dev, "bus negotiator: invalid mode: %d\n", tbn->mode);
+ err = -EINVAL;
+ goto failed;
}
mutex_init(&tbn->dev_mask_mutex);
@@ -309,29 +495,33 @@ static int tbn_probe(struct platform_device *pdev)
complete_all(&tbn->bus_requested);
complete_all(&tbn->bus_released);
- dev_info(tbn->dev,
- "%s: gpios(aoc2ap: %d ap2aoc: %d), mode %d\n",
- __func__, tbn->aoc2ap_gpio, tbn->ap2aoc_gpio, tbn->mode);
-
- dev_dbg(tbn->dev, "bus negotiator initialized: %pK\n", tbn);
+ dev_info(tbn->dev, "bus negotiator initialized: %pK, mode: %d\n", tbn, tbn->mode);
failed:
- if (err)
+ if (err) {
devm_kfree(dev, tbn);
+ tbn_context = NULL;
+ }
return err;
}
static int tbn_remove(struct platform_device *pdev)
{
- struct tbn_context *tbn = dev_get_drvdata(&(pdev->dev));
-
- free_irq(tbn->aoc2ap_irq, tbn);
- if (gpio_is_valid(tbn->aoc2ap_gpio))
- gpio_free(tbn->aoc2ap_gpio);
- if (gpio_is_valid(tbn->aoc2ap_gpio))
- gpio_free(tbn->aoc2ap_gpio);
+ struct device *dev = &pdev->dev;
+ struct tbn_context *tbn = dev_get_drvdata(dev);
+ if (tbn->mode == TBN_MODE_GPIO) {
+ free_irq(tbn->aoc2ap_irq, tbn);
+ if (gpio_is_valid(tbn->aoc2ap_gpio))
+ gpio_free(tbn->aoc2ap_gpio);
+ if (gpio_is_valid(tbn->aoc2ap_gpio))
+ gpio_free(tbn->aoc2ap_gpio);
+#if IS_ENABLED(CONFIG_TOUCHSCREEN_TBN_AOC_CHANNEL_MODE)
+ } else if (tbn->mode == TBN_MODE_AOC_CHANNEL) {
+ kthread_stop(tbn->aoc_channel_task);
+#endif
+ }
return 0;
}
diff --git a/touch_bus_negotiator.h b/touch_bus_negotiator.h
index a4c157e..5697489 100644
--- a/touch_bus_negotiator.h
+++ b/touch_bus_negotiator.h
@@ -6,14 +6,20 @@
#include <linux/notifier.h>
#include <linux/mutex.h>
#include <linux/device.h>
+#include <linux/cdev.h>
+#include <linux/kthread.h>
+
+#define TBN_DEVICE_NAME "tbn"
+#define TBN_CLASS_NAME "tbn"
#define TBN_REQUEST_BUS_TIMEOUT_MS 500
#define TBN_RELEASE_BUS_TIMEOUT_MS 500
enum tbn_mode {
- TBN_MODE_DISABLED,
+ TBN_MODE_DISABLED = 0,
TBN_MODE_GPIO,
- TBN_MODE_MAILBOX,
+ TBN_MODE_AOC_CHANNEL,
+ TBN_MODE_MOCK,
};
enum tbn_bus_owner {
@@ -21,22 +27,49 @@ enum tbn_bus_owner {
TBN_BUS_OWNER_AOC = 1,
};
+enum TbnOperation : __u32 {
+ TBN_OPERATION_IDLE = 0,
+ TBN_OPERATION_AP_RELEASE_BUS,
+ TBN_OPERATION_AP_REQUEST_BUS,
+};
+
+struct TbnEvent {
+ __u32 id;
+ enum TbnOperation operation;
+} __packed;
+
+struct TbnEventResponse {
+ __u32 id;
+ __s32 err;
+ enum TbnOperation operation;
+ bool lptw_triggered;
+} __packed;
+
struct tbn_context {
struct device *dev;
struct completion bus_requested;
struct completion bus_released;
struct mutex dev_mask_mutex;
- u8 mode;
+ u32 mode;
u32 max_devices;
u32 registered_mask;
u32 requested_dev_mask;
int aoc2ap_gpio;
int ap2aoc_gpio;
int aoc2ap_irq;
+ struct task_struct *aoc_channel_task;
+
+ /* event management */
+ struct TbnEventResponse event_resp;
+#if IS_ENABLED(CONFIG_TOUCHSCREEN_TBN_AOC_CHANNEL_MODE)
+ struct TbnEvent event;
+ struct mutex event_lock;
+#endif
};
int register_tbn(u32 *output);
void unregister_tbn(u32 *output);
+int tbn_request_bus_with_result(u32 dev_mask, bool *lptw_triggered);
int tbn_request_bus(u32 dev_mask);
int tbn_release_bus(u32 dev_mask);
diff --git a/touch_offload.c b/touch_offload.c
index 6f2dab8..344b6ae 100644
--- a/touch_offload.c
+++ b/touch_offload.c
@@ -502,7 +502,9 @@ static long touch_offload_ioctl(struct file *file, unsigned int ioctl_num,
(configure.config.filter_palm &&
!context->caps.filter_palm) ||
(configure.config.auto_reporting &&
- !context->caps.auto_reporting)) {
+ !context->caps.auto_reporting) ||
+ (configure.config.coord_filter &&
+ !context->caps.coord_filter)) {
pr_err("%s: Invalid configuration enables unsupported features!\n",
__func__);
err = -EINVAL;
@@ -728,8 +730,6 @@ int touch_offload_cleanup(struct touch_offload_context *context)
{
pr_debug("%s\n", __func__);
- cdev_del(&context->dev);
-
device_destroy(context->cls, context->dev_num);
class_destroy(context->cls);