summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWill McVicker <willmcvicker@google.com>2023-11-03 16:24:57 -0700
committerWill McVicker <willmcvicker@google.com>2023-11-03 16:24:57 -0700
commit0c81a452691e3c1004e638cb09bc3a0282213b21 (patch)
tree90df6daf050c2d85bfc87dce1e240ec5accac7e1
parent07200384a6b3202931b6d1151c6a226124cf8a79 (diff)
parentcb1ce1fb12115861672af8282416ed591b14b038 (diff)
downloadcommon-0c81a452691e3c1004e638cb09bc3a0282213b21.tar.gz
Merge aosp/android-gs-raviole-5.10-android14 into android-gs-raviole-mainline
* aosp/android-gs-raviole-5.10-android14: (115 commits) gti: request GTI_PM_WAKELOCK_TYPE_IRQ when TBN enabled gti: add IRQ wakelock gti: Acquire the wakelock before applying FW settings gti: Adjust the panel_bridge_enable logs level to debug touch/common: add TBN mock mode gti: support predefined dev id to create device goog_touch_interface: Add power supply status gti: report driver status every frame gti: update display status instead of pm_state for screen_state touch_offload: fix delete cdev twice touch/gti: Add coordinate filter input: touch_offload: interface updates gti: add firmware setting logs gti: update the screen state when the driver suspend. gti: remove ignore_screenoff_heatmap gti: remove touch rawdata sysfs command. gti: Correct the probe sequence to initialize the input. gti: Correct the probe sequence to initialize the input. gti: Correct the probe sequence to initialize the input. gti: update driver status for touch_offload gti: support fw water mode status change gti: fix heatmap protection kleaf: add AOC dependency touch/common: refine debugging message touch/common: fix crash when tbn is disabled Revert^2 "touch/common: suppport aoc cannel mode for tbn" Revert "touch/common: suppport aoc cannel mode for tbn" gti: add atrace for offload input report. gti: Support procfs to get heatmap. gti: change the default mode for dumpstate logs. gti: change the default mode for dumpstate logs. gti: Check VRR is enabled or not before setting touch report rate kleaf: add AOC dependencies kleaf: switch to generic label_flags touch/common: return EPROBE_DEFER when the GPIO is invalid. touch/common: return EPROBE_DEFER when the GPIO is invalid. gti: Support procfs to get heatmap. touch/common: suppport aoc cannel mode for tbn gti: Add logs for unexpected tool_type by vendor driver gti: Add logs for unexpected tool_type by vendor driver touch/gti: Add touch index in GTI log touch/gti: Add touch index in GTI log touch: gti: Added wakelock_nosync support touch: gti: Added wakelock_nosync support touch: gti: Fix spi write error. touch: gti: Fix spi write error. gti: replace manual_sensing_lock by input_process_lock touch/gti: Add a new line after showing SS data gti: replace manual_sensing_lock by input_process_lock touch/gti: Only handle display state if changed touch/gti: Add a new line after showing SS data touch/gti: Only handle display state if changed gti: replace manual_sensing_lock by input_process_lock touch_offload: fix mixed use register_chrdev and cdev_add touch/gti: fully remove sysfs when removing gti touch/gti: release all fingers when the device suspends touch/gti: release all fingers when the device suspends touch/gti: release all fingers when the device suspends touch/gti: support variable report rate touch: Add fw_grip and fw_palm sysfs node touch: Add fw_grip and fw_palm sysfs node touch/TBN: Double check the value of aoc2ap_gpio when timeout touch/TBN: Double check the value of aoc2ap_gpio when timeout touch/gti: Correct the typo of firmware status enumeration touch/gti: Transport touch_offload driver/stylus context touch/gti: adjust the output format width by size. heatmap: add vb2_queue_release in module remove touch/gti: Add frame index into atrace. touch/gti: Refine the GTI logs for touch offload. touch/gti: Support custom offload device name from DT. touch/gti: fix data racing touch/gti: Support pm qos. touch/gti: Support pm qos. touch/gti: Support pm qos. touch: common: fix double includes of heatmap.h touch/gti: support the capability check for SPI dma enabled. touch/gti: support the capability check for SPI dma enabled. touch: common: fix double includes of heatmap.h touch/gti: support the capability check for SPI dma enabled. touch/gti: process input after vendor irq complete. touch/gti: process input after vendor irq complete. touch/gti: initialize input abs to support shape algo reporting. touch/gti: initialize input abs to support shape algo reporting. touch/gti: initialize input to support orientation reporting. touch/gti: initialize input to support orientation reporting. touch/gti: support interrupt debug logs. touch/gti: support interrupt debug logs. touch/gti: fix the race condition between drm and pm touch/gti: fix the race condition between drm and pm touch/gti: refine the naming of features enabled. touch/gti: refine the force active. touch/gti: fix build error for 5.15 kernel touch/gti: refine the naming of features enabled. touch/gti: refine the force active. touch/gti: fix offload caps for orientation touch/gti: Support mutual and self sensing data for sysfs touch/gti: add goog_notify_fw_status_changed touch/gti: enable heatamp when updating fw settings. touch/gti: support touch cancel reporting by MT_TOOL_PALM. touch/gti: add the ability to report orientation. ... Change-Id: I0cbc6709e0dffdbed0cefc573bd9aa1490042001 Signed-off-by: Will McVicker <willmcvicker@google.com>
-rw-r--r--BUILD.bazel6
-rw-r--r--Kbuild11
-rw-r--r--Kconfig8
-rw-r--r--Makefile27
-rw-r--r--goog_touch_interface.c2414
-rw-r--r--goog_touch_interface.h285
-rw-r--r--goog_touch_interface_nop.h2
-rw-r--r--heatmap.c8
-rw-r--r--heatmap.h7
-rw-r--r--include/uapi/input/touch_offload.h8
-rw-r--r--touch_bus_negotiator.c284
-rw-r--r--touch_bus_negotiator.h39
-rw-r--r--touch_offload.c67
-rw-r--r--touch_offload.h6
14 files changed, 2350 insertions, 822 deletions
diff --git a/BUILD.bazel b/BUILD.bazel
index 447bc3d..54b14f7 100644
--- a/BUILD.bazel
+++ b/BUILD.bazel
@@ -13,11 +13,12 @@ filegroup(
)
filegroup(
- name = "common.kconfig",
+ name = "touch.common.kconfig",
srcs = glob([
"Kconfig",
]),
visibility = [
+ "//private/devices/google:__subpackages__",
"//private/google-modules/soc/gs:__pkg__",
],
)
@@ -29,6 +30,7 @@ kernel_module(
"**/*.h",
"Kbuild",
]) + [
+ "//private/google-modules/aoc:headers",
"//private/google-modules/display:headers",
"//private/google-modules/display/include:headers",
"//private/google-modules/soc/gs:gs_soc_headers",
@@ -41,10 +43,12 @@ kernel_module(
],
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__",
],
deps = [
+ "//private/google-modules/aoc",
"//private/google-modules/soc/gs:gs_soc_module",
],
)
diff --git a/Kbuild b/Kbuild
deleted file mode 100644
index a42d6f2..0000000
--- a/Kbuild
+++ /dev/null
@@ -1,11 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-ccflags-y += -I$(srctree)/$(src)/include
-ccflags-y += -I$(srctree)/../private/google-modules/display
-ccflags-y += -I$(srctree)/../private/google-modules/display/include/uapi
-
-obj-$(CONFIG_TOUCHSCREEN_TBN) += touch_bus_negotiator.o
-obj-$(CONFIG_TOUCHSCREEN_HEATMAP) += heatmap.o
-obj-$(CONFIG_TOUCHSCREEN_OFFLOAD) += touch_offload.o
-obj-$(CONFIG_GOOG_TOUCH_INTERFACE) += goog_touch_interface.o
-
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/Makefile b/Makefile
index 3cc7e5c..4f90607 100644
--- a/Makefile
+++ b/Makefile
@@ -1,14 +1,31 @@
-# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_TOUCHSCREEN_TBN) += touch_bus_negotiator.o
+obj-$(CONFIG_TOUCHSCREEN_HEATMAP) += heatmap.o
+obj-$(CONFIG_TOUCHSCREEN_OFFLOAD) += touch_offload.o
+obj-$(CONFIG_GOOG_TOUCH_INTERFACE) += goog_touch_interface.o
KERNEL_SRC ?= /lib/modules/$(shell uname -r)/build
M ?= $(shell pwd)
+KBUILD_OPTIONS += CONFIG_TOUCHSCREEN_TBN=m
+KBUILD_OPTIONS += CONFIG_TOUCHSCREEN_HEATMAP=m
+KBUILD_OPTIONS += CONFIG_TOUCHSCREEN_OFFLOAD=m
+KBUILD_OPTIONS += CONFIG_GOOG_TOUCH_INTERFACE=m
EXTRA_CFLAGS += -DDYNAMIC_DEBUG_MODULE
+EXTRA_CFLAGS += -I$(KERNEL_SRC)/../google-modules/touch/common/include
+EXTRA_CFLAGS += -I$(KERNEL_SRC)/../google-modules/display
-include $(KERNEL_SRC)/../private/google-modules/soc/gs/Makefile.include
+modules clean:
+ $(MAKE) -C $(KERNEL_SRC) M=$(M) \
+ $(KBUILD_OPTIONS) \
+ EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \
+ $(@)
-modules modules_install headers_install clean:
+modules_install:
$(MAKE) -C $(KERNEL_SRC) M=$(M) \
- EXTRA_CFLAGS="$(EXTRA_CFLAGS)" KBUILD_EXTRA_SYMBOLS="$(EXTRA_SYMBOLS)" $(@)
+ $(KBUILD_OPTIONS) \
+ EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \
+ $(@)
-modules_install: headers_install
+headers_install:
+ $(MAKE) -C $(KERNEL_SRC) M=$(M) \
+ $(@)
diff --git a/goog_touch_interface.c b/goog_touch_interface.c
index 7766d95..9741aeb 100644
--- a/goog_touch_interface.c
+++ b/goog_touch_interface.c
@@ -8,10 +8,14 @@
#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>
#include "goog_touch_interface.h"
#include "touch_bus_negotiator.h"
+#include "../../../gs-google/drivers/soc/google/vh/kernel/systrace.h"
static struct class *gti_class;
static u8 gti_dev_num;
@@ -20,6 +24,301 @@ 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);
+
+/*-----------------------------------------------------------------------------
+ * GTI/proc: forward declarations, structures and functions.
+ */
+static int goog_proc_ms_base_show(struct seq_file *m, void *v);
+static int goog_proc_ms_diff_show(struct seq_file *m, void *v);
+static int goog_proc_ms_raw_show(struct seq_file *m, void *v);
+static int goog_proc_ss_base_show(struct seq_file *m, void *v);
+static int goog_proc_ss_diff_show(struct seq_file *m, void *v);
+static int goog_proc_ss_raw_show(struct seq_file *m, void *v);
+static struct proc_dir_entry *gti_proc_dir_root;
+static char *gti_proc_name[GTI_PROC_NUM] = {
+ [GTI_PROC_MS_BASE] = "ms_base",
+ [GTI_PROC_MS_DIFF] = "ms_diff",
+ [GTI_PROC_MS_RAW] = "ms_raw",
+ [GTI_PROC_SS_BASE] = "ss_base",
+ [GTI_PROC_SS_DIFF] = "ss_diff",
+ [GTI_PROC_SS_RAW] = "ss_raw",
+};
+static int (*gti_proc_show[GTI_PROC_NUM]) (struct seq_file *, void *) = {
+ [GTI_PROC_MS_BASE] = goog_proc_ms_base_show,
+ [GTI_PROC_MS_DIFF] = goog_proc_ms_diff_show,
+ [GTI_PROC_MS_RAW] = goog_proc_ms_raw_show,
+ [GTI_PROC_SS_BASE] = goog_proc_ss_base_show,
+ [GTI_PROC_SS_DIFF] = goog_proc_ss_diff_show,
+ [GTI_PROC_SS_RAW] = goog_proc_ss_raw_show,
+};
+DEFINE_PROC_SHOW_ATTRIBUTE(goog_proc_ms_base);
+DEFINE_PROC_SHOW_ATTRIBUTE(goog_proc_ms_diff);
+DEFINE_PROC_SHOW_ATTRIBUTE(goog_proc_ms_raw);
+DEFINE_PROC_SHOW_ATTRIBUTE(goog_proc_ss_base);
+DEFINE_PROC_SHOW_ATTRIBUTE(goog_proc_ss_diff);
+DEFINE_PROC_SHOW_ATTRIBUTE(goog_proc_ss_raw);
+
+static void goog_proc_heatmap_show(struct seq_file *m, void *v)
+{
+ struct goog_touch_interface *gti = m->private;
+ struct gti_sensor_data_cmd *cmd = &gti->cmd.manual_sensor_data_cmd;
+ u16 tx = gti->offload.caps.tx_size;
+ u16 rx = gti->offload.caps.rx_size;
+ int x, y;
+
+ if (cmd->size == 0 || cmd->buffer == NULL) {
+ seq_puts(m, "result: N/A!\n");
+ GOOG_WARN(gti, "result: N/A!\n");
+ return;
+ }
+
+ switch (cmd->type) {
+ case GTI_SENSOR_DATA_TYPE_MS_BASELINE:
+ case GTI_SENSOR_DATA_TYPE_MS_DIFF:
+ case GTI_SENSOR_DATA_TYPE_MS_RAW:
+ if (cmd->size == TOUCH_OFFLOAD_DATA_SIZE_2D(rx, tx)) {
+ seq_puts(m, "result:\n");
+ for (y = 0; y < rx; y++) {
+ for (x = 0; x < tx; x++)
+ seq_printf(m, "%5d,", ((s16 *)cmd->buffer)[y * tx + x]);
+ seq_puts(m, "\n");
+ }
+ } else {
+ seq_printf(m, "error: invalid buffer %p or size %d!\n",
+ cmd->buffer, cmd->size);
+ GOOG_WARN(gti, "error: invalid buffer %p or size %d!\n",
+ cmd->buffer, cmd->size);
+ }
+ break;
+
+ case GTI_SENSOR_DATA_TYPE_SS_BASELINE:
+ case GTI_SENSOR_DATA_TYPE_SS_DIFF:
+ case GTI_SENSOR_DATA_TYPE_SS_RAW:
+ if (cmd->size == TOUCH_OFFLOAD_DATA_SIZE_1D(rx, tx)) {
+ seq_puts(m, "result:\n");
+ seq_puts(m, "TX:");
+ for (x = 0; x < tx; x++)
+ seq_printf(m, "%5d,", ((s16 *)cmd->buffer)[x]);
+ seq_puts(m, "\nRX:");
+ for (y = 0; y < rx; y++)
+ seq_printf(m, "%5d,", ((s16 *)cmd->buffer)[tx + y]);
+ seq_puts(m, "\n");
+ } else {
+ seq_printf(m, "error: invalid buffer %p or size %d!\n",
+ cmd->buffer, cmd->size);
+ GOOG_WARN(gti, "error: invalid buffer %p or size %d!\n",
+ cmd->buffer, cmd->size);
+ }
+ break;
+
+ default:
+ seq_printf(m, "error: invalid type %#x!\n", cmd->type);
+ GOOG_ERR(gti, "error: invalid type %#x!\n", cmd->type);
+ break;
+ }
+}
+
+static int goog_proc_heatmap_process(struct seq_file *m, void *v, enum gti_sensor_data_type type)
+{
+ struct goog_touch_interface *gti = m->private;
+ struct gti_sensor_data_cmd *cmd = &gti->cmd.manual_sensor_data_cmd;
+ int ret = 0;
+
+ ret = goog_precheck_heatmap(gti);
+ if (ret) {
+ seq_puts(m, "N/A!\n");
+ goto heatmap_process_err;
+ }
+
+ switch (type) {
+ case GTI_SENSOR_DATA_TYPE_MS_BASELINE:
+ case GTI_SENSOR_DATA_TYPE_MS_DIFF:
+ case GTI_SENSOR_DATA_TYPE_MS_RAW:
+ case GTI_SENSOR_DATA_TYPE_SS_BASELINE:
+ case GTI_SENSOR_DATA_TYPE_SS_DIFF:
+ case GTI_SENSOR_DATA_TYPE_SS_RAW:
+ cmd->type = type;
+ break;
+
+ default:
+ seq_printf(m, "error: invalid type %#x!\n", type);
+ GOOG_ERR(gti, "error: invalid type %#x!\n", type);
+ ret = -EINVAL;
+ break;
+ }
+
+ if (ret)
+ goto heatmap_process_err;
+
+ cmd->buffer = NULL;
+ cmd->size = 0;
+ ret = goog_process_vendor_cmd(gti, GTI_CMD_GET_SENSOR_DATA_MANUAL);
+ if (ret) {
+ seq_printf(m, "error: %d!\n", ret);
+ GOOG_ERR(gti, "error: %d!\n", ret);
+ } else {
+ GOOG_INFO(gti, "type %#x.\n", type);
+ }
+
+heatmap_process_err:
+ if (ret) {
+ cmd->buffer = NULL;
+ cmd->size = 0;
+ }
+ return ret;
+}
+
+static int goog_proc_ms_base_show(struct seq_file *m, void *v)
+{
+ struct goog_touch_interface *gti = m->private;
+ int ret;
+
+ ret = mutex_lock_interruptible(&gti->input_process_lock);
+ if (ret) {
+ seq_puts(m, "error: has been interrupted!\n");
+ GOOG_WARN(gti, "error: has been interrupted!\n");
+ return ret;
+ }
+
+ ret = goog_proc_heatmap_process(m, v, GTI_SENSOR_DATA_TYPE_MS_BASELINE);
+ if (!ret)
+ goog_proc_heatmap_show(m, v);
+ mutex_unlock(&gti->input_process_lock);
+
+ return ret;
+}
+
+static int goog_proc_ms_diff_show(struct seq_file *m, void *v)
+{
+ struct goog_touch_interface *gti = m->private;
+ int ret;
+
+ ret = mutex_lock_interruptible(&gti->input_process_lock);
+ if (ret) {
+ seq_puts(m, "error: has been interrupted!\n");
+ GOOG_WARN(gti, "error: has been interrupted!\n");
+ return ret;
+ }
+ ret = goog_proc_heatmap_process(m, v, GTI_SENSOR_DATA_TYPE_MS_DIFF);
+ if (!ret)
+ goog_proc_heatmap_show(m, v);
+ mutex_unlock(&gti->input_process_lock);
+
+ return ret;
+}
+
+static int goog_proc_ms_raw_show(struct seq_file *m, void *v)
+{
+ struct goog_touch_interface *gti = m->private;
+ int ret;
+
+ ret = mutex_lock_interruptible(&gti->input_process_lock);
+ if (ret) {
+ seq_puts(m, "error: has been interrupted!\n");
+ GOOG_WARN(gti, "error: has been interrupted!\n");
+ return ret;
+ }
+
+ ret = goog_proc_heatmap_process(m, v, GTI_SENSOR_DATA_TYPE_MS_RAW);
+ if (!ret)
+ goog_proc_heatmap_show(m, v);
+ mutex_unlock(&gti->input_process_lock);
+
+ return ret;
+}
+
+static int goog_proc_ss_base_show(struct seq_file *m, void *v)
+{
+ struct goog_touch_interface *gti = m->private;
+ int ret;
+
+ ret = mutex_lock_interruptible(&gti->input_process_lock);
+ if (ret) {
+ seq_puts(m, "error: has been interrupted!\n");
+ GOOG_WARN(gti, "error: has been interrupted!\n");
+ return ret;
+ }
+
+ ret = goog_proc_heatmap_process(m, v, GTI_SENSOR_DATA_TYPE_SS_BASELINE);
+ if (!ret)
+ goog_proc_heatmap_show(m, v);
+ mutex_unlock(&gti->input_process_lock);
+
+ return ret;
+}
+
+static int goog_proc_ss_diff_show(struct seq_file *m, void *v)
+{
+ struct goog_touch_interface *gti = m->private;
+ int ret;
+
+ ret = mutex_lock_interruptible(&gti->input_process_lock);
+ if (ret) {
+ seq_puts(m, "error: has been interrupted!\n");
+ GOOG_WARN(gti, "error: has been interrupted!\n");
+ return ret;
+ }
+
+ ret = goog_proc_heatmap_process(m, v, GTI_SENSOR_DATA_TYPE_SS_DIFF);
+ if (!ret)
+ goog_proc_heatmap_show(m, v);
+ mutex_unlock(&gti->input_process_lock);
+
+ return ret;
+}
+
+static int goog_proc_ss_raw_show(struct seq_file *m, void *v)
+{
+ struct goog_touch_interface *gti = m->private;
+ int ret;
+
+ ret = mutex_lock_interruptible(&gti->input_process_lock);
+ if (ret) {
+ seq_puts(m, "error: has been interrupted!\n");
+ GOOG_WARN(gti, "error: has been interrupted!\n");
+ return ret;
+ }
+
+ ret = goog_proc_heatmap_process(m, v, GTI_SENSOR_DATA_TYPE_SS_RAW);
+ if (!ret)
+ goog_proc_heatmap_show(m, v);
+ mutex_unlock(&gti->input_process_lock);
+
+ return ret;
+}
+
+static void goog_init_proc(struct goog_touch_interface *gti)
+{
+ int type;
+
+ if (!gti_proc_dir_root) {
+ gti_proc_dir_root = proc_mkdir(GTI_NAME, NULL);
+ if (!gti_proc_dir_root) {
+ pr_err("%s: proc_mkdir failed for %s!\n", __func__, GTI_NAME);
+ return;
+ }
+ }
+
+ gti->proc_dir = proc_mkdir_data(dev_name(gti->dev), 0555, gti_proc_dir_root, gti);
+ if (!gti->proc_dir) {
+ GOOG_ERR(gti, "proc_mkdir_data failed!\n");
+ return;
+ }
+
+ for (type = GTI_PROC_MS_BASE; type < GTI_PROC_NUM; type++) {
+ char *name = gti_proc_name[type];
+
+ if (gti_proc_show[type])
+ gti->proc_heatmap[type] = proc_create_single_data(
+ name, 0555, gti->proc_dir, gti_proc_show[type], gti);
+ if (!gti->proc_heatmap[type])
+ GOOG_ERR(gti, "proc_create_single_data failed for %s!\n", name);
+ }
+}
/*-----------------------------------------------------------------------------
* GTI/sysfs: forward declarations, structures and functions.
@@ -28,12 +327,20 @@ 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_ver_show(struct device *dev,
+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 grip_enabled_show(struct device *dev,
+static ssize_t fw_grip_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size);
+static ssize_t fw_palm_show(struct device *dev,
struct device_attribute *attr, char *buf);
-static ssize_t grip_enabled_store(struct device *dev,
+static ssize_t fw_palm_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size);
+static ssize_t fw_ver_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
static ssize_t irq_enabled_show(struct device *dev,
struct device_attribute *attr, char *buf);
static ssize_t irq_enabled_store(struct device *dev,
@@ -42,20 +349,10 @@ 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,
struct device_attribute *attr, const char *buf, size_t size);
-static ssize_t palm_enabled_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size);
-static ssize_t palm_enabled_show(struct device *dev,
- struct device_attribute *attr, char *buf);
static ssize_t ping_show(struct device *dev,
struct device_attribute *attr, char *buf);
static ssize_t reset_show(struct device *dev,
@@ -72,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,
@@ -86,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(grip_enabled);
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_RW(palm_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_grip_enabled.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_palm_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,
};
@@ -140,15 +427,20 @@ static ssize_t force_active_show(
struct device *dev, struct device_attribute *attr, char *buf)
{
struct goog_touch_interface *gti = dev_get_drvdata(dev);
- int ret = 0;
+ ssize_t buf_idx = 0;
bool locked = false;
+ if (gti->ignore_force_active) {
+ GOOG_WARN(gti, "operation not supported!\n");
+ return -EOPNOTSUPP;
+ }
+
locked = goog_pm_wake_check_locked(gti, GTI_PM_WAKELOCK_TYPE_FORCE_ACTIVE);
- ret = snprintf(buf, PAGE_SIZE, "result: %s\n",
+ buf_idx += scnprintf(buf, PAGE_SIZE - buf_idx, "result: %s\n",
locked ? "locked" : "unlocked");
- GOOG_LOG("%s", buf);
+ GOOG_INFO(gti, "%s", buf);
- return ret;
+ return buf_idx;
}
static ssize_t force_active_store(struct device *dev,
@@ -159,383 +451,349 @@ static ssize_t force_active_store(struct device *dev,
int ret = 0;
if (buf == NULL || size < 0) {
- GOOG_LOG("error: invalid input!\n");
+ GOOG_INFO(gti, "error: invalid input!\n");
return -EINVAL;
}
if (kstrtou32(buf, 10, &locked)) {
- GOOG_LOG("error: invalid input!\n");
+ GOOG_INFO(gti, "error: invalid input!\n");
return -EINVAL;
}
if (locked > 1) {
- GOOG_LOG("error: invalid input!\n");
+ GOOG_INFO(gti, "error: invalid input!\n");
return -EINVAL;
}
- if (locked)
- ret = goog_pm_wake_lock(gti, GTI_PM_WAKELOCK_TYPE_FORCE_ACTIVE, false);
- else
- ret = goog_pm_wake_unlock(gti, GTI_PM_WAKELOCK_TYPE_FORCE_ACTIVE);
+ if (locked) {
+ gti_debug_hc_dump(gti);
+ gti_debug_input_dump(gti);
+ if (gti->ignore_force_active)
+ GOOG_WARN(gti, "operation not supported!\n");
+ else
+ ret = goog_pm_wake_lock(gti, GTI_PM_WAKELOCK_TYPE_FORCE_ACTIVE, false);
+ } else {
+ if (gti->ignore_force_active)
+ GOOG_WARN(gti, "operation not supported!\n");
+ else
+ ret = goog_pm_wake_unlock(gti, GTI_PM_WAKELOCK_TYPE_FORCE_ACTIVE);
+ }
if (ret < 0) {
- GOOG_LOG("error: %d!\n", ret);
+ GOOG_INFO(gti, "error: %d!\n", ret);
return ret;
}
return size;
}
-static ssize_t fw_ver_show(struct device *dev,
+static ssize_t fw_coord_filter_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- int ret;
+ 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;
- memset(gti->cmd.fw_version_cmd.buffer, 0, sizeof(gti->cmd.fw_version_cmd.buffer));
- ret = goog_process_vendor_cmd(gti, GTI_CMD_GET_FW_VERSION);
- if (ret == -EOPNOTSUPP) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE,
+ if (!gti->coord_filter_enabled) {
+ 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,
- "error: %d!\n", ret);
- } else {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE,
- "result: %s\n", gti->cmd.fw_version_cmd.buffer);
+ GOOG_INFO(gti, "%s", buf);
+ return buf_idx;
}
- GOOG_LOG("%s", buf);
-
- return buf_idx;
-}
-
-static ssize_t grip_enabled_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_grip_cmd *cmd = &gti->cmd.grip_cmd;
- cmd->setting = GTI_GRIP_DISABLE;
- ret = goog_process_vendor_cmd(gti, GTI_CMD_GET_GRIP_MODE);
+ 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 += 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 += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
"error: %d!\n", ret);
} else {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE,
- "result: %u\n", cmd->setting);
+ buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
+ "result: %u\n", cmd->setting | (gti->ignore_coord_filter_update << 1));
}
- GOOG_LOG("%s", buf);
+ GOOG_INFO(gti, "%s", buf);
return buf_idx;
}
-static ssize_t grip_enabled_store(struct device *dev,
+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);
- struct gti_grip_cmd *cmd = &gti->cmd.grip_cmd;
- bool enabled = false;
+ int fw_coord_filter;
- if (kstrtobool(buf, &enabled)) {
- GOOG_LOG("error: invalid input!\n");
- return size;
+ if (kstrtou32(buf, 10, &fw_coord_filter)) {
+ GOOG_INFO(gti, "error: invalid input!\n");
+ return -EINVAL;
}
- cmd->setting = enabled ? GTI_GRIP_ENABLE : GTI_GRIP_DISABLE;
- ret = goog_process_vendor_cmd(gti, GTI_CMD_SET_GRIP_MODE);
+ 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_LOG("error: not supported!\n");
+ GOOG_INFO(gti, "error: not supported!\n");
else if (ret)
- GOOG_LOG("error: %d!\n", ret);
+ GOOG_INFO(gti, "error: %d!\n", ret);
else
- GOOG_LOG("grip_enabled= %u\n", cmd->setting);
+ GOOG_INFO(gti, "fw_coord_filter= %u\n", fw_coord_filter);
return size;
}
-static ssize_t irq_enabled_show(struct device *dev,
+static ssize_t fw_grip_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- int ret;
+ int ret = 0;
ssize_t buf_idx = 0;
struct goog_touch_interface *gti = dev_get_drvdata(dev);
+ struct gti_grip_cmd *cmd = &gti->cmd.grip_cmd;
- gti->cmd.irq_cmd.setting = GTI_IRQ_MODE_NA;
- ret = goog_process_vendor_cmd(gti, GTI_CMD_GET_IRQ_MODE);
+ cmd->setting = GTI_GRIP_DISABLE;
+ ret = goog_process_vendor_cmd(gti, GTI_CMD_GET_GRIP_MODE);
if (ret == -EOPNOTSUPP) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE,
+ 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 += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
"error: %d!\n", ret);
} else {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE,
- "result: %u\n", gti->cmd.irq_cmd.setting);
+ buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
+ "result: %u\n", cmd->setting | (gti->ignore_grip_update << 1));
}
- GOOG_LOG("%s", buf);
+ GOOG_INFO(gti, "%s", buf);
return buf_idx;
}
-static ssize_t irq_enabled_store(struct device *dev,
+static ssize_t fw_grip_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
- int ret;
- bool enabled;
+ int ret = 0;
struct goog_touch_interface *gti = dev_get_drvdata(dev);
+ int fw_grip_mode = 0;
+ bool enabled = false;
- if (kstrtobool(buf, &enabled)) {
- GOOG_ERR("error: invalid input!\n");
+ if (kstrtou32(buf, 10, &fw_grip_mode)) {
+ GOOG_INFO(gti, "error: invalid input!\n");
return size;
}
- gti->cmd.irq_cmd.setting = enabled;
- ret = goog_process_vendor_cmd(gti, GTI_CMD_SET_IRQ_MODE);
+ enabled = fw_grip_mode & 0x01;
+ gti->ignore_grip_update = (fw_grip_mode >> 1) & 0x01;
+ gti->cmd.grip_cmd.setting = enabled ? GTI_GRIP_ENABLE : GTI_GRIP_DISABLE;
+ ret = goog_process_vendor_cmd(gti, GTI_CMD_SET_GRIP_MODE);
if (ret == -EOPNOTSUPP)
- GOOG_LOG("error: not supported!\n");
+ GOOG_INFO(gti, "error: not supported!\n");
else if (ret)
- GOOG_LOG("error: %d!\n", ret);
+ GOOG_INFO(gti, "error: %d!\n", ret);
else
- GOOG_LOG("irq_enabled= %u\n", gti->cmd.irq_cmd.setting);
+ GOOG_INFO(gti, "fw_grip_mode: %u\n", fw_grip_mode);
return size;
}
-static ssize_t mf_mode_show(struct device *dev,
+static ssize_t fw_palm_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_palm_cmd *cmd = &gti->cmd.palm_cmd;
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE,
- "result: %u\n", gti->mf_mode);
- GOOG_LOG("%s", buf);
+ cmd->setting = GTI_PALM_DISABLE;
+ ret = goog_process_vendor_cmd(gti, GTI_CMD_GET_PALM_MODE);
+ 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_palm_update << 1));
+ }
+ GOOG_INFO(gti, "%s", buf);
return buf_idx;
}
-static ssize_t mf_mode_store(struct device *dev,
+static ssize_t fw_palm_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);
- enum gti_mf_mode mode = 0;
-
- if (buf == NULL || size < 0) {
- GOOG_LOG("error: invalid input!\n");
- return size;
- }
-
- if (kstrtou32(buf, 10, &mode)) {
- GOOG_LOG("error: invalid input!\n");
- return size;
- }
+ int fw_palm_mode;
+ bool enabled;
- if (mode < GTI_MF_MODE_UNFILTER ||
- mode > GTI_MF_MODE_AUTO_REPORT) {
- GOOG_LOG("error: invalid input!\n");
- return size;
+ if (kstrtou32(buf, 10, &fw_palm_mode)) {
+ GOOG_INFO(gti, "error: invalid input!\n");
+ return -EINVAL;
}
- gti->mf_mode = mode;
- GOOG_LOG("mf_mode= %u\n", gti->mf_mode);
+ enabled = fw_palm_mode & 0x01;
+ gti->ignore_palm_update = (fw_palm_mode >> 1) & 0x01;
+ gti->cmd.palm_cmd.setting = enabled ? GTI_PALM_ENABLE : GTI_PALM_DISABLE;
+ ret = goog_process_vendor_cmd(gti, GTI_CMD_SET_PALM_MODE);
+ 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_palm_mode= %u\n", fw_palm_mode);
return size;
}
-static ssize_t ms_base_show(struct device *dev,
+static ssize_t fw_ver_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ int ret;
ssize_t buf_idx = 0;
struct goog_touch_interface *gti = dev_get_drvdata(dev);
- struct gti_sensor_data_cmd *cmd = &gti->cmd.sensor_data_cmd;
- int ret = 0;
- u16 tx = gti->offload.caps.tx_size;
- u16 rx = gti->offload.caps.rx_size;
- int x, y;
- 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);
+ memset(gti->cmd.fw_version_cmd.buffer, 0, sizeof(gti->cmd.fw_version_cmd.buffer));
+ ret = goog_process_vendor_cmd(gti, GTI_CMD_GET_FW_VERSION);
if (ret == -EOPNOTSUPP) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE,
+ 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 += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
"error: %d!\n", ret);
} else {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE, "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,
- "%5d,", ((s16 *)cmd->buffer)[y * tx + x]);
- }
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE, "\n");
- }
- GOOG_LOG("%s", buf);
- }
+ buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
+ "result: %s\n", gti->cmd.fw_version_cmd.buffer);
}
+ GOOG_INFO(gti, "%s", buf);
+
return buf_idx;
}
-static ssize_t ms_diff_show(struct device *dev,
+static ssize_t irq_enabled_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ int ret;
ssize_t buf_idx = 0;
struct goog_touch_interface *gti = dev_get_drvdata(dev);
- struct gti_sensor_data_cmd *cmd = &gti->cmd.sensor_data_cmd;
- int ret = 0;
- u16 tx = gti->offload.caps.tx_size;
- u16 rx = gti->offload.caps.rx_size;
- int x, y;
- 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);
+ gti->cmd.irq_cmd.setting = GTI_IRQ_MODE_NA;
+ ret = goog_process_vendor_cmd(gti, GTI_CMD_GET_IRQ_MODE);
if (ret == -EOPNOTSUPP) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE,
+ 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 += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
"error: %d!\n", ret);
} else {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE, "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,
- "%5d,", ((s16 *)cmd->buffer)[y * tx + x]);
- }
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE, "\n");
- }
- GOOG_LOG("%s", buf);
- }
+ buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
+ "result: %u\n", gti->cmd.irq_cmd.setting);
}
+ GOOG_INFO(gti, "%s", buf);
+
return buf_idx;
}
-static ssize_t ms_raw_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t irq_enabled_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
{
- ssize_t buf_idx = 0;
+ int ret;
+ bool enabled;
struct goog_touch_interface *gti = dev_get_drvdata(dev);
- struct gti_sensor_data_cmd *cmd = &gti->cmd.sensor_data_cmd;
- int ret = 0;
- u16 tx = gti->offload.caps.tx_size;
- u16 rx = gti->offload.caps.rx_size;
- int x, y;
- 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);
- if (ret == -EOPNOTSUPP) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE,
- "error: not supported!\n");
- } else if (ret) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE,
- "error: %d!\n", ret);
- } else {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE, "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,
- "%5d,", ((s16 *)cmd->buffer)[y * tx + x]);
- }
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE, "\n");
- }
- GOOG_LOG("%s", buf);
- }
+ if (kstrtobool(buf, &enabled)) {
+ GOOG_ERR(gti, "error: invalid input!\n");
+ return size;
}
- return buf_idx;
+
+ gti->cmd.irq_cmd.setting = enabled;
+ ret = goog_process_vendor_cmd(gti, GTI_CMD_SET_IRQ_MODE);
+ if (ret == -EOPNOTSUPP)
+ GOOG_INFO(gti, "error: not supported!\n");
+ else if (ret)
+ GOOG_INFO(gti, "error: %d!\n", ret);
+ else
+ GOOG_INFO(gti, "irq_enabled= %u\n", gti->cmd.irq_cmd.setting);
+
+ return size;
}
-static ssize_t offload_enabled_show(struct device *dev,
+static ssize_t mf_mode_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->offload_enable);
- GOOG_LOG("%s", buf);
+ buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
+ "result: %u\n", gti->mf_mode);
+ GOOG_INFO(gti, "%s", buf);
return buf_idx;
}
-static ssize_t offload_enabled_store(struct device *dev,
+static ssize_t mf_mode_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
struct goog_touch_interface *gti = dev_get_drvdata(dev);
+ enum gti_mf_mode mode = 0;
- if (kstrtobool(buf, &gti->offload_enable)) {
- GOOG_LOG("error: invalid input!\n");
- } else {
- GOOG_LOG("offload_enable= %d\n", gti->offload_enable);
- /* Force to turn off offload by request. */
- if (!gti->offload_enable)
- goog_offload_set_running(gti, false);
+ if (buf == NULL || size < 0) {
+ GOOG_INFO(gti, "error: invalid input!\n");
+ return size;
}
+ if (kstrtou32(buf, 10, &mode)) {
+ GOOG_INFO(gti, "error: invalid input!\n");
+ return size;
+ }
+
+ if (mode < GTI_MF_MODE_UNFILTER ||
+ mode > GTI_MF_MODE_AUTO_REPORT) {
+ GOOG_INFO(gti, "error: invalid input!\n");
+ return size;
+ }
+
+ gti->mf_mode = mode;
+ GOOG_INFO(gti, "mf_mode= %u\n", gti->mf_mode);
+
return size;
}
-static ssize_t palm_enabled_show(struct device *dev,
+static ssize_t offload_enabled_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_palm_cmd *cmd = &gti->cmd.palm_cmd;
- cmd->setting = GTI_PALM_DISABLE;
- ret = goog_process_vendor_cmd(gti, GTI_CMD_GET_PALM_MODE);
- if (ret == -EOPNOTSUPP) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE,
- "error: not supported!\n");
- } else if (ret) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE,
- "error: %d!\n", ret);
- } else {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE,
- "result: %u\n", cmd->setting);
- }
- GOOG_LOG("%s", buf);
+ buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
+ "result: %d\n", gti->offload_enabled);
+ GOOG_INFO(gti, "%s", buf);
return buf_idx;
}
-static ssize_t palm_enabled_store(struct device *dev,
+static ssize_t offload_enabled_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);
- struct gti_palm_cmd *cmd = &gti->cmd.palm_cmd;
- bool enabled = false;
- if (kstrtobool(buf, &enabled)) {
- GOOG_LOG("error: invalid input!\n");
- return -EINVAL;
+ if (kstrtobool(buf, &gti->offload_enabled)) {
+ GOOG_INFO(gti, "error: invalid input!\n");
+ } else {
+ GOOG_INFO(gti, "offload_enabled= %d\n", gti->offload_enabled);
+ /* Force to turn off offload by request. */
+ if (!gti->offload_enabled)
+ goog_offload_set_running(gti, false);
}
- cmd->setting = enabled ? GTI_PALM_ENABLE : GTI_PALM_DISABLE;
- ret = goog_process_vendor_cmd(gti, GTI_CMD_SET_PALM_MODE);
- if (ret == -EOPNOTSUPP)
- GOOG_LOG("error: not supported!\n");
- else if (ret)
- GOOG_LOG("error: %d!\n", ret);
- else
- GOOG_LOG("palm_enabled= %u\n", cmd->setting);
-
return size;
}
@@ -549,18 +807,18 @@ static ssize_t ping_show(struct device *dev,
gti->cmd.ping_cmd.setting = GTI_PING_ENABLE;
ret = goog_process_vendor_cmd(gti, GTI_CMD_PING);
if (ret == -EOPNOTSUPP) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE,
+ buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
"error: not supported!\n");
gti->cmd.ping_cmd.setting = GTI_PING_NA;
} else if (ret) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE,
+ buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
"error: %d!\n", ret);
gti->cmd.ping_cmd.setting = GTI_PING_NA;
} else {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE,
+ buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
"result: success.\n");
}
- GOOG_LOG("%s", buf);
+ GOOG_INFO(gti, "%s", buf);
return buf_idx;
}
@@ -573,13 +831,13 @@ static ssize_t reset_show(struct device *dev,
if (gti->cmd.reset_cmd.setting == GTI_RESET_MODE_NOP ||
gti->cmd.reset_cmd.setting == GTI_RESET_MODE_NA) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE,
+ buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
"error: %d!\n", gti->cmd.reset_cmd.setting);
} else {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE,
+ buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
"result: success.\n");
}
- GOOG_LOG("%s", buf);
+ GOOG_INFO(gti, "%s", buf);
return buf_idx;
}
@@ -592,31 +850,31 @@ static ssize_t reset_store(struct device *dev,
enum gti_reset_mode mode = 0;
if (buf == NULL || size < 0) {
- GOOG_LOG("error: invalid input!\n");
+ GOOG_INFO(gti, "error: invalid input!\n");
return -EINVAL;
}
if (kstrtou32(buf, 10, &mode)) {
- GOOG_LOG("error: invalid input!\n");
+ GOOG_INFO(gti, "error: invalid input!\n");
return -EINVAL;
}
if (mode <= GTI_RESET_MODE_NOP ||
mode > GTI_RESET_MODE_AUTO) {
- GOOG_LOG("error: invalid input!\n");
+ GOOG_INFO(gti, "error: invalid input!\n");
return -EINVAL;
}
gti->cmd.reset_cmd.setting = mode;
ret = goog_process_vendor_cmd(gti, GTI_CMD_RESET);
if (ret == -EOPNOTSUPP) {
- GOOG_LOG("error: not supported!\n");
+ GOOG_INFO(gti, "error: not supported!\n");
gti->cmd.reset_cmd.setting = GTI_RESET_MODE_NA;
} else if (ret) {
- GOOG_LOG("error: %d!\n", ret);
+ GOOG_INFO(gti, "error: %d!\n", ret);
gti->cmd.reset_cmd.setting = GTI_RESET_MODE_NA;
} else {
- GOOG_LOG("reset= 0x%x\n", mode);
+ GOOG_INFO(gti, "reset= 0x%x\n", mode);
}
return size;
@@ -632,16 +890,16 @@ static ssize_t scan_mode_show(struct device *dev,
gti->cmd.scan_cmd.setting = GTI_SCAN_MODE_NA;
ret = goog_process_vendor_cmd(gti, GTI_CMD_GET_SCAN_MODE);
if (ret == -EOPNOTSUPP) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE,
+ 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 += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
"error: %d!\n", ret);
} else {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE,
+ buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
"result: %u\n", gti->cmd.scan_cmd.setting);
}
- GOOG_LOG("%s", buf);
+ GOOG_INFO(gti, "%s", buf);
return buf_idx;
}
@@ -654,29 +912,29 @@ static ssize_t scan_mode_store(struct device *dev,
enum gti_scan_mode mode = 0;
if (buf == NULL || size < 0) {
- GOOG_LOG("error: invalid input!\n");
+ GOOG_INFO(gti, "error: invalid input!\n");
return size;
}
if (kstrtou32(buf, 10, &mode)) {
- GOOG_ERR("error: invalid input!\n");
+ GOOG_ERR(gti, "error: invalid input!\n");
return size;
}
if (mode < GTI_SCAN_MODE_AUTO ||
mode > GTI_SCAN_MODE_LP_IDLE) {
- GOOG_LOG("error: invalid input!\n");
+ GOOG_INFO(gti, "error: invalid input!\n");
return size;
}
gti->cmd.scan_cmd.setting = mode;
ret = goog_process_vendor_cmd(gti, GTI_CMD_SET_SCAN_MODE);
if (ret == -EOPNOTSUPP)
- GOOG_ERR("error: not supported!\n");
+ GOOG_ERR(gti, "error: not supported!\n");
else if (ret)
- GOOG_ERR("error: %d!\n", ret);
+ GOOG_ERR(gti, "error: %d!\n", ret);
else
- GOOG_LOG("scan_mode= %u\n", mode);
+ GOOG_INFO(gti, "scan_mode= %u\n", mode);
return size;
}
@@ -690,18 +948,18 @@ static ssize_t screen_protector_mode_enabled_store(struct device *dev,
bool enabled = false;
if (kstrtobool(buf, &enabled)) {
- GOOG_ERR("invalid input!\n");
+ GOOG_ERR(gti, "invalid input!\n");
return -EINVAL;
}
cmd->setting = enabled ? GTI_SCREEN_PROTECTOR_MODE_ENABLE : GTI_SCREEN_PROTECTOR_MODE_DISABLE;
ret = goog_process_vendor_cmd(gti, GTI_CMD_SET_SCREEN_PROTECTOR_MODE);
if (ret == -EOPNOTSUPP)
- GOOG_ERR("error: not supported!\n");
+ GOOG_ERR(gti, "error: not supported!\n");
else if (ret)
- GOOG_ERR("error: %d!\n", ret);
+ GOOG_ERR(gti, "error: %d!\n", ret);
else
- GOOG_LOG("enabled= %u\n", enabled);
+ GOOG_INFO(gti, "enabled= %u\n", enabled);
gti->screen_protector_mode_setting = enabled ?
GTI_SCREEN_PROTECTOR_MODE_ENABLE : GTI_SCREEN_PROTECTOR_MODE_DISABLE;
return size;
@@ -711,20 +969,20 @@ static ssize_t screen_protector_mode_enabled_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
int ret = 0;
- size_t size = 0;
+ ssize_t buf_idx = 0;
struct goog_touch_interface *gti = dev_get_drvdata(dev);
struct gti_screen_protector_mode_cmd *cmd = &gti->cmd.screen_protector_mode_cmd;
cmd->setting = GTI_SCREEN_PROTECTOR_MODE_NA;
ret = goog_process_vendor_cmd(gti, GTI_CMD_GET_SCREEN_PROTECTOR_MODE);
if (ret == 0) {
- size += scnprintf(buf, PAGE_SIZE, "result: %d\n",
+ buf_idx += scnprintf(buf, PAGE_SIZE - buf_idx, "result: %d\n",
cmd->setting == GTI_SCREEN_PROTECTOR_MODE_ENABLE);
} else {
- size += scnprintf(buf, PAGE_SIZE, "error: %d\n", ret);
+ buf_idx += scnprintf(buf, PAGE_SIZE - buf_idx, "error: %d\n", ret);
}
- GOOG_LOG("%s", buf);
- return size;
+ GOOG_INFO(gti, "%s", buf);
+ return buf_idx;
}
static ssize_t self_test_show(struct device *dev,
@@ -738,151 +996,25 @@ static ssize_t self_test_show(struct device *dev,
memset(gti->cmd.selftest_cmd.buffer, 0, sizeof(gti->cmd.selftest_cmd.buffer));
ret = goog_process_vendor_cmd(gti, GTI_CMD_SELFTEST);
if (ret == -EOPNOTSUPP) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE,
+ 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 += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
"error: %d!\n", ret);
} else {
if (gti->cmd.selftest_cmd.result == GTI_SELFTEST_RESULT_DONE) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE,
+ buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
"result: %s\n", gti->cmd.selftest_cmd.buffer);
} else if (gti->cmd.selftest_cmd.result ==
GTI_SELFTEST_RESULT_SHELL_CMDS_REDIRECT) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE,
+ buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
"redirect: %s\n", gti->cmd.selftest_cmd.buffer);
} else {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE, "error: N/A!\n");
- }
- }
- GOOG_LOG("%s", buf);
-
- 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.sensor_data_cmd;
- int ret = 0;
- u16 tx = gti->offload.caps.tx_size;
- u16 rx = gti->offload.caps.rx_size;
- int x, y;
-
- 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);
- if (ret == -EOPNOTSUPP) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE,
- "error: not supported!\n");
- } else if (ret) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE,
- "error: %d!\n", ret);
- } else {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE, "result:\n");
- if (cmd->buffer &&
- cmd->size == TOUCH_OFFLOAD_DATA_SIZE_2D(rx, tx)) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE, "TX:");
- for (x = 0; x < tx; x++) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE,
- "%5d,", ((s16 *)cmd->buffer)[x]);
- }
-
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE, "\nRX:");
- for (y = 0; y < rx; y++) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE,
- "%5d,", ((s16 *)cmd->buffer)[tx + y]);
- }
- GOOG_LOG("%s", buf);
+ buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx, "error: N/A!\n");
}
}
- 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.sensor_data_cmd;
- int ret = 0;
- u16 tx = gti->offload.caps.tx_size;
- u16 rx = gti->offload.caps.rx_size;
- int x, y;
-
- 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);
- if (ret == -EOPNOTSUPP) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE,
- "error: not supported!\n");
- } else if (ret) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE,
- "error: %d!\n", ret);
- } else {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE, "result:\n");
- if (cmd->buffer &&
- cmd->size == TOUCH_OFFLOAD_DATA_SIZE_2D(rx, tx)) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE, "TX:");
- for (x = 0; x < tx; x++) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE,
- "%5d,", ((s16 *)cmd->buffer)[x]);
- }
-
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE, "\nRX:");
- for (y = 0; y < rx; y++) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE,
- "%5d,", ((s16 *)cmd->buffer)[tx + y]);
- }
- GOOG_LOG("%s", buf);
- }
- }
- return buf_idx;
-}
+ GOOG_INFO(gti, "%s", buf);
-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.sensor_data_cmd;
- int ret = 0;
- u16 tx = gti->offload.caps.tx_size;
- u16 rx = gti->offload.caps.rx_size;
- int x, y;
-
- 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);
- if (ret == -EOPNOTSUPP) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE,
- "error: not supported!\n");
- } else if (ret) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE,
- "error: %d!\n", ret);
- } else {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE, "result:\n");
- if (cmd->buffer &&
- cmd->size == TOUCH_OFFLOAD_DATA_SIZE_2D(rx, tx)) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE, "TX:");
- for (x = 0; x < tx; x++) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE,
- "%5d,", ((s16 *)cmd->buffer)[x]);
- }
-
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE, "\nRX:");
- for (y = 0; y < rx; y++) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE,
- "%5d,", ((s16 *)cmd->buffer)[tx + y]);
- }
- GOOG_LOG("%s", buf);
- }
- }
return buf_idx;
}
@@ -896,16 +1028,16 @@ static ssize_t sensing_enabled_show(struct device *dev,
gti->cmd.sensing_cmd.setting = GTI_SENSING_MODE_NA;
ret = goog_process_vendor_cmd(gti, GTI_CMD_GET_SENSING_MODE);
if (ret == -EOPNOTSUPP) {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE,
+ 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 += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
"error: %d!\n", ret);
} else {
- buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE,
+ buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
"result: %u\n", gti->cmd.sensing_cmd.setting);
}
- GOOG_LOG("%s", buf);
+ GOOG_INFO(gti, "%s", buf);
return buf_idx;
}
@@ -918,18 +1050,18 @@ static ssize_t sensing_enabled_store(struct device *dev,
struct goog_touch_interface *gti = dev_get_drvdata(dev);
if (kstrtobool(buf, &enabled)) {
- GOOG_LOG("error: invalid input!\n");
+ GOOG_INFO(gti, "error: invalid input!\n");
return size;
}
gti->cmd.sensing_cmd.setting = enabled;
ret = goog_process_vendor_cmd(gti, GTI_CMD_SET_SENSING_MODE);
if (ret == -EOPNOTSUPP)
- GOOG_LOG("error: not supported!\n");
+ GOOG_INFO(gti, "error: not supported!\n");
else if (ret)
- GOOG_LOG("error: %d!\n", ret);
+ GOOG_INFO(gti, "error: %d!\n", ret);
else
- GOOG_LOG("sensing_enabled= %u\n", gti->cmd.sensing_cmd.setting);
+ GOOG_INFO(gti, "sensing_enabled= %u\n", gti->cmd.sensing_cmd.setting);
return size;
}
@@ -940,9 +1072,9 @@ static ssize_t v4l2_enabled_show(struct device *dev,
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->v4l2_enable);
- GOOG_LOG("%s", buf);
+ buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE - buf_idx,
+ "result: %d\n", gti->v4l2_enabled);
+ GOOG_INFO(gti, "%s", buf);
return buf_idx;
}
@@ -952,10 +1084,41 @@ static ssize_t v4l2_enabled_store(struct device *dev,
{
struct goog_touch_interface *gti = dev_get_drvdata(dev);
- if (kstrtobool(buf, &gti->v4l2_enable))
- GOOG_LOG("error: invalid input!\n");
+ if (kstrtobool(buf, &gti->v4l2_enabled))
+ GOOG_INFO(gti, "error: invalid input!\n");
else
- GOOG_LOG("v4l2_enable= %d\n", gti->v4l2_enable);
+ GOOG_INFO(gti, "v4l2_enabled= %d\n", gti->v4l2_enabled);
+
+ 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;
}
@@ -964,12 +1127,80 @@ static ssize_t v4l2_enabled_store(struct device *dev,
* Debug: functions.
*/
#ifdef GTI_DEBUG_KFIFO_LEN
+inline void gti_debug_hc_push(struct goog_touch_interface *gti)
+{
+ /*
+ * Use kfifo as circular buffer by skipping one element
+ * when fifo is full.
+ */
+ if (kfifo_is_full(&gti->debug_fifo_hc))
+ kfifo_skip(&gti->debug_fifo_hc);
+ kfifo_in(&gti->debug_fifo_hc, &gti->debug_hc, 1);
+}
+
+inline int gti_debug_hc_pop(struct goog_touch_interface *gti,
+ struct gti_debug_health_check *fifo, unsigned int len)
+{
+ if (len > GTI_DEBUG_KFIFO_LEN) {
+ GOOG_ERR(gti, "invalid fifo pop len(%d)!\n", len);
+ return -EINVAL;
+ }
+ /*
+ * Keep data without pop-out to support different timing
+ * print-out by each caller.
+ */
+ return kfifo_out_peek(&gti->debug_fifo_hc, fifo, len) == len ? 0 : -EFAULT;
+}
+
+inline void gti_debug_hc_update(struct goog_touch_interface *gti, bool from_top_half)
+{
+ if (from_top_half) {
+ gti->debug_hc.irq_time = ktime_get();
+ gti->debug_hc.irq_index = gti->irq_index;
+ } else {
+ gti->debug_hc.input_index = gti->input_index;
+ gti->debug_hc.slot_bit_active = gti->slot_bit_active;
+ gti_debug_hc_push(gti);
+ }
+}
+
+void gti_debug_hc_dump(struct goog_touch_interface *gti)
+{
+ int ret;
+ u64 i, count;
+ s64 delta;
+ s64 sec_delta;
+ u32 ms_delta;
+ ktime_t current_time = ktime_get();
+ struct gti_debug_health_check last_fifo[GTI_DEBUG_KFIFO_LEN] = { 0 };
+
+ count = min_t(u64, gti->irq_index, ARRAY_SIZE(last_fifo));
+ ret = gti_debug_hc_pop(gti, last_fifo, count);
+ if (ret) {
+ GOOG_ERR(gti, "Failed to peek debug hc, err: %d\n", ret);
+ return;
+ }
+ for (i = 0 ; i < count ; i++) {
+ sec_delta = -1;
+ ms_delta = 0;
+ /*
+ * Calculate the delta time between irq triggered and current time.
+ */
+ delta = ktime_ms_delta(current_time, last_fifo[i].irq_time);
+ if (delta > 0)
+ sec_delta = div_u64_rem(delta, MSEC_PER_SEC, &ms_delta);
+ GOOG_LOG(gti, "dump-int: #%llu(%lld.%u): C#%llu(0x%lx).\n",
+ last_fifo[i].irq_index, sec_delta, ms_delta,
+ last_fifo[i].input_index, last_fifo[i].slot_bit_active);
+ }
+}
+
inline void gti_debug_input_push(struct goog_touch_interface *gti, int slot)
{
struct gti_debug_input fifo;
if (slot < 0 || slot >= MAX_SLOTS) {
- GOOG_ERR("Invalid slot: %d\n", slot);
+ GOOG_ERR(gti, "Invalid slot: %d\n", slot);
return;
}
@@ -977,18 +1208,18 @@ inline void gti_debug_input_push(struct goog_touch_interface *gti, int slot)
* Use kfifo as circular buffer by skipping one element
* when fifo is full.
*/
- if (kfifo_is_full(&gti->debug_fifo))
- kfifo_skip(&gti->debug_fifo);
+ if (kfifo_is_full(&gti->debug_fifo_input))
+ kfifo_skip(&gti->debug_fifo_input);
memcpy(&fifo, &gti->debug_input[slot], sizeof(struct gti_debug_input));
- kfifo_in(&gti->debug_fifo, &fifo, 1);
+ kfifo_in(&gti->debug_fifo_input, &fifo, 1);
}
inline int gti_debug_input_pop(struct goog_touch_interface *gti,
struct gti_debug_input *fifo, unsigned int len)
{
if (len > GTI_DEBUG_KFIFO_LEN) {
- GOOG_ERR("invalid fifo pop len(%d)!\n", len);
+ GOOG_ERR(gti, "invalid fifo pop len(%d)!\n", len);
return -EINVAL;
}
@@ -996,23 +1227,26 @@ inline int gti_debug_input_pop(struct goog_touch_interface *gti,
* Keep coords without pop-out to support different timing
* print-out by each caller.
*/
- return kfifo_out_peek(&gti->debug_fifo, fifo, len) == len ? 0 : -EFAULT;
+ return kfifo_out_peek(&gti->debug_fifo_input, fifo, len) == len ? 0 : -EFAULT;
}
inline void gti_debug_input_update(struct goog_touch_interface *gti)
{
int slot;
+ u64 irq_index = gti->irq_index;
ktime_t time = ktime_get();
for_each_set_bit(slot, &gti->slot_bit_changed, MAX_SLOTS) {
if (test_bit(slot, &gti->slot_bit_active)) {
gti->debug_input[slot].pressed.time = time;
+ gti->debug_input[slot].pressed.irq_index = irq_index;
memcpy(&gti->debug_input[slot].pressed.coord,
&gti->offload.coords[slot],
sizeof(struct TouchOffloadCoord));
} else {
- gti->released_count++;
+ gti->released_index++;
gti->debug_input[slot].released.time = time;
+ gti->debug_input[slot].released.irq_index = irq_index;
memcpy(&gti->debug_input[slot].released.coord,
&gti->offload.coords[slot],
sizeof(struct TouchOffloadCoord));
@@ -1024,8 +1258,8 @@ inline void gti_debug_input_update(struct goog_touch_interface *gti)
void gti_debug_input_dump(struct goog_touch_interface *gti)
{
- int ret = 0;
- int i, slot, count;
+ int slot, ret;
+ u64 i, count;
s64 delta;
s64 sec_delta_down;
u32 ms_delta_down;
@@ -1035,17 +1269,16 @@ void gti_debug_input_dump(struct goog_touch_interface *gti)
ktime_t current_time = ktime_get();
struct gti_debug_input last_fifo[GTI_DEBUG_KFIFO_LEN] = { 0 };
- count = min(gti->released_count, ARRAY_SIZE(last_fifo));
+ count = min_t(u64, gti->released_index, ARRAY_SIZE(last_fifo));
ret = gti_debug_input_pop(gti, last_fifo, count);
- if (ret != 0) {
- GOOG_ERR("Failed to peek debug input, err: %d\n", ret);
+ if (ret) {
+ GOOG_ERR(gti, "Failed to peek debug input, err: %d\n", ret);
return;
}
-
for (i = 0 ; i < count ; i++) {
if (last_fifo[i].slot < 0 ||
last_fifo[i].slot >= MAX_SLOTS) {
- GOOG_LOG("dump: #%d: invalid slot #!\n", last_fifo[i].slot);
+ GOOG_INFO(gti, "dump: #%d: invalid slot #!\n", last_fifo[i].slot);
continue;
}
sec_delta_down = -1;
@@ -1077,19 +1310,21 @@ void gti_debug_input_dump(struct goog_touch_interface *gti)
last_fifo[i].pressed.coord.y;
}
}
- GOOG_LOG("dump: #%d: %lld.%u(%lld.%u) D(%d, %d).\n",
+
+ GOOG_LOG(gti, "dump: #%d: %lld.%u(%lld.%u) D(%d, %d) I(%llu, %llu).\n",
last_fifo[i].slot,
sec_delta_down, ms_delta_down,
sec_delta_duration, ms_delta_duration,
- px_delta_x, px_delta_y);
- GOOG_DBG("dump-dbg: #%d: P(%u, %u) -> R(%u, %u).\n\n",
+ px_delta_x, px_delta_y,
+ last_fifo[i].pressed.irq_index, last_fifo[i].released.irq_index);
+ GOOG_DBG(gti, "dump-dbg: #%d: P(%u, %u) -> R(%u, %u).\n\n",
last_fifo[i].slot,
last_fifo[i].pressed.coord.x, last_fifo[i].pressed.coord.y,
last_fifo[i].released.coord.x, last_fifo[i].released.coord.y);
}
/* Extra check for unexpected case. */
for_each_set_bit(slot, &gti->slot_bit_active, MAX_SLOTS) {
- GOOG_LOG("slot #%d is not released after suspend!\n", slot);
+ GOOG_INFO(gti, "slot #%d is active!\n", slot);
}
}
#endif /* GTI_DEBUG_KFIFO_LEN */
@@ -1099,28 +1334,19 @@ void gti_debug_input_dump(struct goog_touch_interface *gti)
*/
static void panel_bridge_enable(struct drm_bridge *bridge)
{
- int ret = 0;
struct goog_touch_interface *gti =
container_of(bridge, struct goog_touch_interface, panel_bridge);
if (gti->panel_is_lp_mode) {
- GOOG_LOG("skip screen-on because of panel_is_lp_mode enabled!\n");
+ GOOG_DBG(gti, "skip screen-on because of panel_is_lp_mode enabled!\n");
return;
}
- GOOG_LOG("screen-on.\n");
-
- goog_pm_wake_lock(gti, GTI_PM_WAKELOCK_TYPE_SCREEN_ON, false);
-
- gti->cmd.display_state_cmd.setting = GTI_DISPLAY_STATE_ON;
- ret = goog_process_vendor_cmd(gti, GTI_CMD_NOTIFY_DISPLAY_STATE);
- if (ret && ret != -EOPNOTSUPP)
- GOOG_WARN("unexpected vendor_cmd return(%d)!\n", ret);
+ goog_set_display_state(gti, GTI_DISPLAY_STATE_ON);
}
static void panel_bridge_disable(struct drm_bridge *bridge)
{
- int ret = 0;
struct goog_touch_interface *gti =
container_of(bridge, struct goog_touch_interface, panel_bridge);
@@ -1131,14 +1357,7 @@ static void panel_bridge_disable(struct drm_bridge *bridge)
return;
}
- GOOG_LOG("screen-off.\n");
-
- goog_pm_wake_unlock(gti, GTI_PM_WAKELOCK_TYPE_SCREEN_ON);
-
- gti->cmd.display_state_cmd.setting = GTI_DISPLAY_STATE_OFF;
- ret = goog_process_vendor_cmd(gti, GTI_CMD_NOTIFY_DISPLAY_STATE);
- if (ret && ret != -EOPNOTSUPP)
- GOOG_WARN("unexpected vendor_cmd return(%d)!\n", ret);
+ goog_set_display_state(gti, GTI_DISPLAY_STATE_OFF);
}
struct drm_connector *get_bridge_connector(struct drm_bridge *bridge)
@@ -1180,19 +1399,13 @@ 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_LOG("panel_is_lp_mode changed from %d to %d.\n",
+ 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_pm_wake_unlock(gti, GTI_PM_WAKELOCK_TYPE_SCREEN_ON);
- gti->cmd.display_state_cmd.setting = GTI_DISPLAY_STATE_OFF;
- } else {
- goog_pm_wake_lock(gti, GTI_PM_WAKELOCK_TYPE_SCREEN_ON, false);
- gti->cmd.display_state_cmd.setting = GTI_DISPLAY_STATE_ON;
- }
- ret = goog_process_vendor_cmd(gti, GTI_CMD_NOTIFY_DISPLAY_STATE);
- if (ret && ret != -EOPNOTSUPP)
- GOOG_WARN("unexpected return(%d)!", ret);
+
+ if (panel_is_lp_mode)
+ goog_set_display_state(gti, GTI_DISPLAY_STATE_OFF);
+ else
+ goog_set_display_state(gti, GTI_DISPLAY_STATE_ON);
}
gti->panel_is_lp_mode = panel_is_lp_mode;
@@ -1200,13 +1413,17 @@ static void panel_bridge_mode_set(struct drm_bridge *bridge,
int vrefresh = drm_mode_vrefresh(mode);
if (gti->display_vrefresh != vrefresh) {
- GOOG_DBG("display_vrefresh(Hz) changed to %d from %d.\n",
+ GOOG_DBG(gti, "display_vrefresh(Hz) changed to %d from %d.\n",
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("unexpected return(%d)!", ret);
+ GOOG_WARN(gti, "unexpected return(%d)!", ret);
+
+ if (gti->vrr_enabled)
+ goog_lookup_touch_report_rate(gti);
}
}
}
@@ -1219,7 +1436,7 @@ static const struct drm_bridge_funcs panel_bridge_funcs = {
static int register_panel_bridge(struct goog_touch_interface *gti)
{
- GOOG_LOG("\n");
+ GOOG_INFO(gti, "\n");
#ifdef CONFIG_OF
gti->panel_bridge.of_node = gti->vendor_dev->of_node;
#endif
@@ -1231,9 +1448,11 @@ static int register_panel_bridge(struct goog_touch_interface *gti)
static void unregister_panel_bridge(struct drm_bridge *bridge)
{
+ struct goog_touch_interface *gti =
+ container_of(bridge, struct goog_touch_interface, panel_bridge);
struct drm_bridge *node;
- GOOG_LOG("\n");
+ GOOG_INFO(gti, "\n");
drm_bridge_remove(bridge);
if (!bridge->dev) /* not attached */
@@ -1255,6 +1474,77 @@ static void unregister_panel_bridge(struct drm_bridge *bridge)
/*-----------------------------------------------------------------------------
* GTI: functions.
*/
+static int goog_precheck_heatmap(struct goog_touch_interface *gti)
+{
+ int ret = 0;
+
+ /*
+ * 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;
+}
+
+static void goog_set_display_state(struct goog_touch_interface *gti,
+ enum gti_display_state_setting display_state)
+{
+ int ret = 0;
+
+ if (gti->display_state == display_state)
+ return;
+
+ switch (display_state) {
+ case GTI_DISPLAY_STATE_OFF:
+ GOOG_INFO(gti, "screen-off.\n");
+ ret = goog_pm_wake_unlock_nosync(gti, GTI_PM_WAKELOCK_TYPE_SCREEN_ON);
+ if (ret < 0)
+ GOOG_INFO(gti, "Error while obtaining screen-off wakelock: %d!\n", ret);
+
+ break;
+ case GTI_DISPLAY_STATE_ON:
+ GOOG_INFO(gti, "screen-on.\n");
+ ret = goog_pm_wake_lock_nosync(gti, GTI_PM_WAKELOCK_TYPE_SCREEN_ON, false);
+ if (ret < 0)
+ GOOG_INFO(gti, "Error while obtaining screen-on wakelock: %d!\n", ret);
+
+ break;
+ default:
+ GOOG_ERR(gti, "Unexpected value(0x%X) of display state parameter.\n",
+ 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);
+ if (ret && ret != -EOPNOTSUPP)
+ GOOG_WARN(gti, "Unexpected vendor_cmd return(%d)!\n", ret);
+}
+
+bool goog_check_spi_dma_enabled(struct spi_device *spi_dev)
+{
+ bool ret = false;
+
+ if (spi_dev && spi_dev->controller) {
+ struct device_node *np = spi_dev->controller->dev.of_node;
+
+ /*
+ * Check the SPI controller(s3c64xx-spi) whether support DMA
+ * or not.
+ */
+ ret = of_property_read_bool(np, "dma-mode");
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL(goog_check_spi_dma_enabled);
+
int goog_process_vendor_cmd(struct goog_touch_interface *gti, enum gti_cmd_type cmd_type)
{
void *private_data = gti->vendor_private_data;
@@ -1271,6 +1561,16 @@ int goog_process_vendor_cmd(struct goog_touch_interface *gti, enum gti_cmd_type
case GTI_CMD_SELFTEST:
ret = gti->options.selftest(private_data, &gti->cmd.selftest_cmd);
break;
+ case GTI_CMD_GET_CONTEXT_DRIVER:
+ ret = gti->options.get_context_driver(private_data, &gti->cmd.context_driver_cmd);
+ break;
+ 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;
@@ -1302,6 +1602,15 @@ int goog_process_vendor_cmd(struct goog_touch_interface *gti, enum gti_cmd_type
private_data, &gti->cmd.sensor_data_cmd);
}
break;
+ case GTI_CMD_GET_SENSOR_DATA_MANUAL:
+ if (gti->cmd.manual_sensor_data_cmd.type & TOUCH_SCAN_TYPE_MUTUAL) {
+ ret = gti->options.get_mutual_sensor_data(
+ private_data, &gti->cmd.manual_sensor_data_cmd);
+ } else if (gti->cmd.manual_sensor_data_cmd.type & TOUCH_SCAN_TYPE_SELF) {
+ ret = gti->options.get_self_sensor_data(
+ private_data, &gti->cmd.manual_sensor_data_cmd);
+ }
+ break;
case GTI_CMD_NOTIFY_DISPLAY_STATE:
ret = gti->options.notify_display_state(private_data,
&gti->cmd.display_state_cmd);
@@ -1314,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:
@@ -1324,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);
@@ -1345,7 +1673,10 @@ int goog_process_vendor_cmd(struct goog_touch_interface *gti, enum gti_cmd_type
/* Take unsupported cmd_type as debug logs for compatibility check. */
if (ret == -EOPNOTSUPP) {
- GOOG_DBG("unsupported request cmd_type %#x!\n", cmd_type);
+ 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;
}
@@ -1410,7 +1741,7 @@ void goog_update_motion_filter(struct goog_touch_interface *gti, unsigned long s
ret = goog_process_vendor_cmd(gti, GTI_CMD_SET_CONTINUOUS_REPORT);
if (ret)
- GOOG_WARN("unexpected return(%d)!", ret);
+ GOOG_WARN(gti, "unexpected return(%d)!", ret);
}
gti->mf_state = next_state;
@@ -1426,7 +1757,7 @@ bool goog_v4l2_read_frame_cb(struct v4l2_heatmap *v4l2)
memcpy(v4l2->frame, gti->heatmap_buf, v4l2_size);
ret = true;
} else {
- GOOG_ERR("wrong pointer(%p) or size (W: %lu, H: %lu) vs %u\n",
+ GOOG_ERR(gti, "wrong pointer(%p) or size (W: %lu, H: %lu) vs %u\n",
gti->heatmap_buf, gti->v4l2.width, gti->v4l2.height, gti->heatmap_buf_size);
}
@@ -1435,10 +1766,28 @@ bool goog_v4l2_read_frame_cb(struct v4l2_heatmap *v4l2)
void goog_v4l2_read(struct goog_touch_interface *gti, ktime_t timestamp)
{
- if (gti->v4l2_enable)
+ if (gti->v4l2_enabled)
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)
{
@@ -1446,7 +1795,7 @@ void goog_offload_populate_coordinate_channel(struct goog_touch_interface *gti,
struct TouchOffloadDataCoord *dc;
if (channel < 0 || channel >= MAX_CHANNELS) {
- GOOG_ERR("Invalid channel: %d\n", channel);
+ GOOG_ERR(gti, "Invalid channel: %d\n", channel);
return;
}
@@ -1472,7 +1821,7 @@ void goog_offload_populate_mutual_channel(struct goog_touch_interface *gti,
struct TouchOffloadData2d *mutual;
if (channel < 0 || channel >= MAX_CHANNELS) {
- GOOG_ERR("Invalid channel: %d\n", channel);
+ GOOG_ERR(gti, "Invalid channel: %d\n", channel);
return;
}
@@ -1492,7 +1841,7 @@ void goog_offload_populate_self_channel(struct goog_touch_interface *gti,
struct TouchOffloadData1d *self;
if (channel < 0 || channel >= MAX_CHANNELS) {
- GOOG_ERR("Invalid channel: %d\n", channel);
+ GOOG_ERR(gti, "Invalid channel: %d\n", channel);
return;
}
@@ -1506,10 +1855,114 @@ void goog_offload_populate_self_channel(struct goog_touch_interface *gti,
memcpy(self->data, buffer, size);
}
+static void goog_offload_populate_driver_status_channel(
+ struct goog_touch_interface *gti,
+ struct touch_offload_frame *frame, int channel,
+ struct gti_context_driver_cmd *driver_cmd)
+{
+ struct TouchOffloadDriverStatus *ds =
+ (struct TouchOffloadDriverStatus *)frame->channel_data[channel];
+
+ memset(ds, 0, frame->channel_data_size[channel]);
+ ds->header.channel_type = (u32)CONTEXT_CHANNEL_TYPE_DRIVER_STATUS;
+ ds->header.channel_size = sizeof(struct TouchOffloadDriverStatus);
+
+ ds->contents.screen_state = driver_cmd->context_changed.screen_state;
+ ds->screen_state = driver_cmd->screen_state;
+
+ 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->context_changed.touch_report_rate;
+ ds->touch_report_rate = driver_cmd->touch_report_rate;
+
+ 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;
+}
+
+static void goog_offload_populate_stylus_status_channel(
+ struct goog_touch_interface *gti,
+ struct touch_offload_frame *frame, int channel,
+ struct gti_context_stylus_cmd *stylus_cmd)
+{
+ struct TouchOffloadStylusStatus *ss =
+ (struct TouchOffloadStylusStatus *)frame->channel_data[channel];
+
+ memset(ss, 0, frame->channel_data_size[channel]);
+ ss->header.channel_type = (u32)CONTEXT_CHANNEL_TYPE_STYLUS_STATUS;
+ ss->header.channel_size = sizeof(struct TouchOffloadStylusStatus);
+
+ ss->contents.coords = stylus_cmd->contents.coords;
+ ss->coords[0] = stylus_cmd->pen_offload_coord;
+
+ ss->contents.coords_timestamp = stylus_cmd->contents.coords_timestamp;
+ ss->coords_timestamp = stylus_cmd->pen_offload_coord_timestamp;
+
+ ss->contents.pen_paired = stylus_cmd->contents.pen_paired;
+ ss->pen_paired = stylus_cmd->pen_paired;
+
+ ss->contents.pen_active = stylus_cmd->contents.pen_active;
+ 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)
+ struct touch_offload_frame *frame, bool reset_data)
{
static u64 index;
+ char trace_tag[128];
u32 channel_type;
int i;
int ret;
@@ -1517,11 +1970,13 @@ void goog_offload_populate_frame(struct goog_touch_interface *gti,
u16 rx = gti->offload.caps.rx_size;
struct gti_sensor_data_cmd *cmd = &gti->cmd.sensor_data_cmd;
+ scnprintf(trace_tag, sizeof(trace_tag), "%s: IDX=%llu IN_TS=%lld.\n",
+ __func__, index, gti->input_timestamp);
+ ATRACE_BEGIN(trace_tag);
+
frame->header.index = index++;
frame->header.timestamp = gti->input_timestamp;
- ATRACE_BEGIN(__func__);
-
/*
* TODO(b/201610482):
* Porting for other channels, like driver status, stylus status
@@ -1531,18 +1986,35 @@ void goog_offload_populate_frame(struct goog_touch_interface *gti,
/* Populate all channels */
for (i = 0; i < frame->num_channels; i++) {
channel_type = frame->channel_type[i];
- GOOG_DBG("#%d: get data(type %#x) from vendor driver", i, channel_type);
+ GOOG_DBG(gti, "#%d: get data(type %#x) from vendor driver", i, channel_type);
ret = 0;
cmd->buffer = NULL;
cmd->size = 0;
- if (channel_type == TOUCH_DATA_TYPE_COORD) {
+ if (channel_type == CONTEXT_CHANNEL_TYPE_DRIVER_STATUS) {
+ ATRACE_BEGIN("populate driver context");
+ ret = goog_get_driver_status(gti, &gti->cmd.context_driver_cmd);
+ if (ret == 0)
+ goog_offload_populate_driver_status_channel(
+ gti, frame, i,
+ &gti->cmd.context_driver_cmd);
+ ATRACE_END();
+ } else if (channel_type == CONTEXT_CHANNEL_TYPE_STYLUS_STATUS) {
+ ATRACE_BEGIN("populate stylus context");
+ ret = goog_process_vendor_cmd(gti, GTI_CMD_GET_CONTEXT_STYLUS);
+ if (ret == 0)
+ goog_offload_populate_stylus_status_channel(
+ gti, frame, i,
+ &gti->cmd.context_stylus_cmd);
+ ATRACE_END();
+ } else if (channel_type == TOUCH_DATA_TYPE_COORD) {
ATRACE_BEGIN("populate coord");
goog_offload_populate_coordinate_channel(gti, frame, i);
ATRACE_END();
} else if (channel_type & TOUCH_SCAN_TYPE_MUTUAL) {
ATRACE_BEGIN("populate mutual data");
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 == TOUCH_OFFLOAD_DATA_SIZE_2D(rx, tx)) {
goog_offload_populate_mutual_channel(gti, frame, i,
@@ -1555,17 +2027,20 @@ 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;
- 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,
cmd->buffer, cmd->size);
}
ATRACE_END();
+ } else {
+ GOOG_ERR(gti, "unrecognized channel_type %#x.\n", channel_type);
}
if (ret) {
- GOOG_DBG("skip to populate data(type %#x, ret %d)!\n",
+ GOOG_DBG(gti, "skip to populate data(type %#x, ret %d)!\n",
channel_type, ret);
}
}
@@ -1575,39 +2050,83 @@ void goog_offload_populate_frame(struct goog_touch_interface *gti,
void goog_update_fw_settings(struct goog_touch_interface *gti)
{
+ int error;
int ret = 0;
- if (gti->offload.offload_running && gti->offload.config.filter_grip)
- gti->cmd.grip_cmd.setting = GTI_GRIP_DISABLE;
- else
- gti->cmd.grip_cmd.setting = gti->default_grip_enabled;
- ret = goog_process_vendor_cmd(gti, GTI_CMD_SET_GRIP_MODE);
- if (ret)
- GOOG_WARN("unexpected return(%d)!", ret);
+ bool enabled = false;
- if (gti->offload.offload_running && gti->offload.config.filter_palm)
- gti->cmd.palm_cmd.setting = GTI_PALM_DISABLE;
- else
- gti->cmd.palm_cmd.setting = gti->default_palm_enabled;
- ret = goog_process_vendor_cmd(gti, GTI_CMD_SET_PALM_MODE);
- if (ret)
- GOOG_WARN("unexpected return(%d)!", ret);
+ error = goog_pm_wake_lock_nosync(gti, GTI_PM_WAKELOCK_TYPE_FW_SETTINGS, true);
+ if (error < 0) {
+ GOOG_DBG(gti, "Error while obtaining FW_SETTINGS wakelock: %d!\n", error);
+ return;
+ }
+
+ if(!gti->ignore_grip_update) {
+ if (gti->offload.offload_running && gti->offload.config.filter_grip)
+ gti->cmd.grip_cmd.setting = GTI_GRIP_DISABLE;
+ else
+ gti->cmd.grip_cmd.setting = gti->default_grip_enabled;
+ ret = goog_process_vendor_cmd(gti, GTI_CMD_SET_GRIP_MODE);
+ if (ret)
+ GOOG_WARN(gti, "unexpected return(%d)!", ret);
+ }
+
+ if(!gti->ignore_palm_update) {
+ if (gti->offload.offload_running && gti->offload.config.filter_palm)
+ gti->cmd.palm_cmd.setting = GTI_PALM_DISABLE;
+ else
+ gti->cmd.palm_cmd.setting = gti->default_palm_enabled;
+ ret = goog_process_vendor_cmd(gti, GTI_CMD_SET_PALM_MODE);
+ if (ret)
+ 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)
- GOOG_ERR("Failed to %s screen protector mode!\n",
- gti->screen_protector_mode_setting == GTI_SCREEN_PROTECTOR_MODE_ENABLE ?
- "enable" : "disable");
+ GOOG_ERR(gti, "Failed to %s screen protector mode!\n",
+ gti->screen_protector_mode_setting == GTI_SCREEN_PROTECTOR_MODE_ENABLE ?
+ "enable" : "disable");
gti->cmd.heatmap_cmd.setting = GTI_HEATMAP_ENABLE;
ret = goog_process_vendor_cmd(gti, GTI_CMD_SET_HEATMAP_ENABLED);
if (ret != 0)
- GOOG_ERR("Failed to enable heatmap!\n");
+ 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");
+ }
+
+ error = goog_pm_wake_unlock_nosync(gti, GTI_PM_WAKELOCK_TYPE_FW_SETTINGS);
+ if (error < 0)
+ GOOG_DBG(gti, "Error while releasing FW_SETTING wakelock: %d!\n", error);
}
static void goog_offload_set_running(struct goog_touch_interface *gti, bool running)
{
if (gti->offload.offload_running != 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);
}
@@ -1620,9 +2139,17 @@ void goog_offload_input_report(void *handle,
bool touch_down = 0;
unsigned int tool_type = MT_TOOL_FINGER;
int i;
+ int error;
unsigned long slot_bit_active = 0;
+ char trace_tag[128];
+ ktime_t ktime = ktime_get();
- ATRACE_BEGIN(__func__);
+ scnprintf(trace_tag, sizeof(trace_tag),
+ "%s: IDX=%lld IN_TS=%lld TS=%lld DELTA=%lld ns.\n",
+ __func__, report->index,
+ ktime_to_ns(report->timestamp), ktime_to_ns(ktime),
+ ktime_to_ns(ktime_sub(ktime, report->timestamp)));
+ ATRACE_BEGIN(trace_tag);
goog_input_lock(gti);
input_set_timestamp(gti->vendor_input_dev, report->timestamp);
@@ -1673,20 +2200,69 @@ void goog_offload_input_report(void *handle,
if (touch_down)
goog_v4l2_read(gti, report->timestamp);
+ error = goog_pm_wake_lock(gti, GTI_PM_WAKELOCK_TYPE_OFFLOAD_REPORT, true);
+ if (error < 0) {
+ GOOG_WARN(gti, "Error while obtaining OFFLOAD_REPORT wakelock: %d!\n", error);
+ ATRACE_END();
+ return;
+ }
goog_update_motion_filter(gti, slot_bit_active);
-
+ error = goog_pm_wake_unlock(gti, GTI_PM_WAKELOCK_TYPE_OFFLOAD_REPORT);
+ if (error < 0)
+ GOOG_WARN(gti, "Error while releasing OFFLOAD_REPORT wakelock: %d!\n", error);
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_DBG(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;
u16 values[2];
struct device_node *np = gti->vendor_dev->of_node;
+ const char *offload_dev_name = NULL;
+
+ /*
+ * TODO(b/201610482): rename DEVICE_NAME in touch_offload.h for more specific.
+ */
+ if (!of_property_read_string(np, "goog,offload-device-name", &offload_dev_name)) {
+ scnprintf(gti->offload.device_name, sizeof(gti->offload.device_name),
+ "%s_%s", DEVICE_NAME, offload_dev_name);
+ }
if (of_property_read_u8_array(np, "goog,touch_offload_id",
gti->offload_id_byte, 4)) {
- GOOG_LOG("set default offload id: GOOG!\n");
+ GOOG_INFO(gti, "set default offload id: GOOG!\n");
gti->offload_id_byte[0] = 'G';
gti->offload_id_byte[1] = 'O';
gti->offload_id_byte[2] = 'O';
@@ -1702,7 +2278,7 @@ int goog_offload_probe(struct goog_touch_interface *gti)
gti->offload.caps.display_width = values[0];
gti->offload.caps.display_height = values[1];
} else {
- GOOG_ERR("Plesae set \"goog,display-resolution\" in dts!");
+ GOOG_ERR(gti, "Please set \"goog,display-resolution\" in dts!");
}
if (of_property_read_u16_array(np, "goog,channel-num",
@@ -1710,7 +2286,7 @@ int goog_offload_probe(struct goog_touch_interface *gti)
gti->offload.caps.tx_size = values[0];
gti->offload.caps.rx_size = values[1];
} else {
- GOOG_ERR("Plesae set \"goog,channel-num\" in dts!");
+ GOOG_ERR(gti, "Please set \"goog,channel-num\" in dts!");
ret = -EINVAL;
goto err_offload_probe;
}
@@ -1735,9 +2311,14 @@ int goog_offload_probe(struct goog_touch_interface *gti)
gti->offload.caps.touch_scan_types =
TOUCH_SCAN_TYPE_MUTUAL;
}
- GOOG_LOG("offload.caps: data_types %#x, scan_types %#x.\n",
+ if (of_property_read_u16(np, "goog,offload-caps-context-channel-types",
+ &gti->offload.caps.context_channel_types)) {
+ gti->offload.caps.context_channel_types = 0;
+ }
+ GOOG_INFO(gti, "offload.caps: data_types %#x, scan_types %#x, context_channel_types %#x.\n",
gti->offload.caps.touch_data_types,
- gti->offload.caps.touch_scan_types);
+ gti->offload.caps.touch_scan_types,
+ gti->offload.caps.context_channel_types);
gti->offload.caps.continuous_reporting = true;
gti->offload.caps.noise_reporting = false;
@@ -1746,6 +2327,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");
@@ -1754,28 +2337,31 @@ int goog_offload_probe(struct goog_touch_interface *gti)
gti->offload.report_cb = goog_offload_input_report;
ret = touch_offload_init(&gti->offload);
if (ret) {
- GOOG_ERR("offload init failed, ret %d!\n", ret);
+ GOOG_ERR(gti, "offload init failed, ret %d!\n", ret);
goto err_offload_probe;
}
- gti->offload_enable = of_property_read_bool(np, "goog,offload-enable");
- GOOG_LOG("offload.caps: display W/H: %d * %d (Tx/Rx: %d * %d).\n",
+ gti->offload_enabled = of_property_read_bool(np, "goog,offload-enabled");
+ GOOG_INFO(gti, "offload.caps: display W/H: %d * %d (Tx/Rx: %d * %d).\n",
gti->offload.caps.display_width, gti->offload.caps.display_height,
gti->offload.caps.tx_size, gti->offload.caps.rx_size);
- GOOG_LOG("offload ID: \"%c%c%c%c\" / 0x%08X, offload_enable=%d.\n",
+ GOOG_INFO(gti, "offload ID: \"%c%c%c%c\" / 0x%08X, offload_enabled=%d.\n",
gti->offload_id_byte[0], gti->offload_id_byte[1], gti->offload_id_byte[2],
- gti->offload_id_byte[3], gti->offload_id, gti->offload_enable);
+ gti->offload_id_byte[3], gti->offload_id, gti->offload_enabled);
gti->default_grip_enabled = of_property_read_bool(np,
"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);
if (!gti->heatmap_buf) {
- GOOG_ERR("heamap alloc failed!\n");
+ GOOG_ERR(gti, "heamap alloc failed!\n");
ret = -ENOMEM;
goto err_offload_probe;
}
@@ -1800,12 +2386,20 @@ int goog_offload_probe(struct goog_touch_interface *gti)
ret = heatmap_probe(&gti->v4l2);
if (ret) {
- GOOG_ERR("v4l2 init failed, ret %d!\n", ret);
+ GOOG_ERR(gti, "v4l2 init failed, ret %d!\n", ret);
+ goto err_offload_probe;
+ }
+ gti->v4l2_enabled = of_property_read_bool(np, "goog,v4l2-enabled");
+ 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;
}
- gti->v4l2_enable = of_property_read_bool(np, "goog,v4l2-enable");
- GOOG_LOG("v4l2 W/H=(%lu, %lu), v4l2_enable=%d.\n",
- gti->v4l2.width, gti->v4l2.height, gti->v4l2_enable);
err_offload_probe:
return ret;
@@ -1818,29 +2412,37 @@ void goog_offload_remove(struct goog_touch_interface *gti)
bool goog_input_legacy_report(struct goog_touch_interface *gti)
{
- if (!gti->offload.offload_running || gti->force_legacy_report)
+ if (!gti->offload.offload_running)
return true;
return false;
}
-int goog_input_process(struct goog_touch_interface *gti)
+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;
- if (gti->offload_enable) {
+ /*
+ * Increase the input index when any slot bit changed which
+ * means the finger is down or up.
+ */
+ if (gti->slot_bit_changed)
+ gti->input_index++;
+
+ if (gti->offload_enabled) {
ret = touch_offload_reserve_frame(&gti->offload, frame);
if (ret != 0 || frame == NULL) {
- GOOG_ERR("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);
/*
@@ -1851,10 +2453,10 @@ int goog_input_process(struct goog_touch_interface *gti)
ret = -EBUSY;
} else {
goog_offload_set_running(gti, true);
- goog_offload_populate_frame(gti, *frame);
+ goog_offload_populate_frame(gti, *frame, reset_data);
ret = touch_offload_queue_frame(&gti->offload, *frame);
if (ret)
- GOOG_ERR("failed to queue reserved frame(ret %d)!\n", ret);
+ GOOG_ERR(gti, "failed to queue reserved frame(ret %d)!\n", ret);
else
gti->offload_frame = NULL;
}
@@ -1865,7 +2467,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 && gti->v4l2_enable) {
+ if (!gti->offload.offload_running && gti->v4l2_enabled) {
int ret;
struct gti_sensor_data_cmd *cmd = &gti->cmd.sensor_data_cmd;
@@ -1873,7 +2475,7 @@ int goog_input_process(struct goog_touch_interface *gti)
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);
@@ -1904,18 +2506,6 @@ void goog_input_set_timestamp(
struct goog_touch_interface *gti,
struct input_dev *dev, ktime_t timestamp)
{
- /* Specific case to handle all fingers release. */
- if (!ktime_compare(timestamp, KTIME_RELEASE_ALL)) {
- GOOG_DBG("Enable force_legacy_report for all fingers release.\n");
- timestamp = ktime_get();
- gti->force_legacy_report = true;
- } else {
- if (gti->force_legacy_report) {
- GOOG_DBG("Disable force_legacy_report as usual state.\n");
- gti->force_legacy_report = false;
- }
- }
-
if (goog_input_legacy_report(gti))
input_set_timestamp(dev, timestamp);
@@ -1929,7 +2519,7 @@ void goog_input_mt_slot(
struct input_dev *dev, int slot)
{
if (slot < 0 || slot >= MAX_SLOTS) {
- GOOG_ERR("Invalid slot: %d\n", slot);
+ GOOG_ERR(gti, "Invalid slot: %d\n", slot);
return;
}
@@ -1942,7 +2532,7 @@ void goog_input_mt_slot(
* This is for input report switch between offload and legacy.
*/
if (!gti->slot_bit_in_use && !gti->input_timestamp_changed)
- GOOG_ERR("please exec goog_input_set_timestamp before %s!\n", __func__);
+ GOOG_ERR(gti, "please exec goog_input_set_timestamp before %s!\n", __func__);
set_bit(slot, &gti->slot_bit_in_use);
}
EXPORT_SYMBOL(goog_input_mt_slot);
@@ -1954,7 +2544,8 @@ void goog_input_mt_report_slot_state(
if (goog_input_legacy_report(gti))
input_mt_report_slot_state(dev, tool_type, active);
- if (tool_type == MT_TOOL_FINGER) {
+ switch (tool_type) {
+ case MT_TOOL_FINGER:
if (active) {
gti->offload.coords[gti->slot].status = COORD_STATUS_FINGER;
if (!test_and_set_bit(gti->slot,
@@ -1968,7 +2559,16 @@ void goog_input_mt_report_slot_state(
set_bit(gti->slot, &gti->slot_bit_changed);
}
}
+ break;
+
+ default:
+ if (!goog_input_legacy_report(gti)) {
+ GOOG_WARN(gti, "unexcepted input tool_type(%#x) active(%d)!\n",
+ tool_type, active);
+ }
+ break;
}
+
}
EXPORT_SYMBOL(goog_input_mt_report_slot_state);
@@ -2020,21 +2620,59 @@ void goog_input_sync(struct goog_touch_interface *gti, struct input_dev *dev)
}
EXPORT_SYMBOL(goog_input_sync);
+void goog_input_release_all_fingers(struct goog_touch_interface *gti)
+{
+ int i;
+
+ goog_input_lock(gti);
+
+ goog_input_set_timestamp(gti, gti->vendor_input_dev, ktime_get());
+ for (i = 0; i < MAX_SLOTS; i++) {
+ goog_input_mt_slot(gti, gti->vendor_input_dev, i);
+ goog_input_mt_report_slot_state(
+ gti, gti->vendor_input_dev, MT_TOOL_FINGER, false);
+ }
+ goog_input_report_key(gti, gti->vendor_input_dev, BTN_TOUCH, 0);
+ goog_input_sync(gti, gti->vendor_input_dev);
+
+ goog_input_unlock(gti);
+
+ goog_input_process(gti, true);
+}
+
void goog_register_tbn(struct goog_touch_interface *gti)
{
struct device_node *np = gti->vendor_dev->of_node;
- gti->tbn_enable = of_property_read_bool(np, "goog,tbn-enable");
- if (gti->tbn_enable) {
+ gti->tbn_enabled = of_property_read_bool(np, "goog,tbn-enabled");
+ if (gti->tbn_enabled) {
if (register_tbn(&gti->tbn_register_mask)) {
- GOOG_ERR("failed to register tbn context!\n");
- gti->tbn_enable = false;
+ GOOG_ERR(gti, "failed to register tbn context!\n");
+ gti->tbn_enabled = false;
} else {
- GOOG_LOG("tbn_register_mask = %#x.\n", gti->tbn_register_mask);
+ GOOG_INFO(gti, "tbn_register_mask = %#x.\n", gti->tbn_register_mask);
}
}
}
+static int goog_get_context_driver_nop(
+ void *private_data, struct gti_context_driver_cmd *cmd)
+{
+ return -ESRCH;
+}
+
+static int goog_get_context_stylus_nop(
+ void *private_data, struct gti_context_stylus_cmd *cmd)
+{
+ 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)
{
@@ -2125,6 +2763,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)
{
@@ -2149,6 +2793,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)
{
@@ -2167,10 +2817,81 @@ static int goog_set_sensing_mode_nop(
return -ESRCH;
}
+void goog_init_input(struct goog_touch_interface *gti)
+{
+ int i;
+
+ if (!gti)
+ return;
+
+ INIT_KFIFO(gti->debug_fifo_hc);
+ INIT_KFIFO(gti->debug_fifo_input);
+ for (i = 0 ; i < MAX_SLOTS ; i++)
+ gti->debug_input[i].slot = i;
+
+ if (gti->vendor_dev && gti->vendor_input_dev) {
+ /*
+ * Initialize the ABS_MT_ORIENTATION to support orientation reporting.
+ * Initialize the ABS_MT_TOUCH_MAJOR and ABS_MT_TOUCH_MINOR depending on
+ * the larger values of ABS_MT_POSITION_X and ABS_MT_POSITION_Y to support
+ * shape algo reporting.
+ */
+ if (gti->offload.caps.rotation_reporting) {
+ int abs_x_max = input_abs_get_max(gti->vendor_input_dev, ABS_MT_POSITION_X);
+ int abs_x_min = input_abs_get_min(gti->vendor_input_dev, ABS_MT_POSITION_X);
+ int abs_x_res = input_abs_get_res(gti->vendor_input_dev, ABS_MT_POSITION_X);
+ int abs_y_max = input_abs_get_max(gti->vendor_input_dev, ABS_MT_POSITION_Y);
+ int abs_y_min = input_abs_get_min(gti->vendor_input_dev, ABS_MT_POSITION_Y);
+ int abs_y_res = input_abs_get_res(gti->vendor_input_dev, ABS_MT_POSITION_Y);
+ int abs_major_max = abs_x_max;
+ int abs_major_min = abs_x_min;
+ int abs_major_res = abs_x_res;
+ int abs_minor_max = abs_y_max;
+ int abs_minor_min = abs_y_min;
+ int abs_minor_res = abs_y_res;
+
+ if (abs_x_max < abs_y_max) {
+ swap(abs_major_max, abs_minor_max);
+ swap(abs_major_min, abs_minor_min);
+ swap(abs_major_res, abs_minor_res);
+ }
+ input_set_abs_params(gti->vendor_input_dev, ABS_MT_ORIENTATION,
+ -4096, 4096, 0, 0);
+ input_set_abs_params(gti->vendor_input_dev, ABS_MT_TOUCH_MAJOR,
+ abs_major_min, abs_major_max, 0, 0);
+ input_set_abs_params(gti->vendor_input_dev, ABS_MT_TOUCH_MINOR,
+ abs_minor_min, abs_minor_max, 0, 0);
+ input_abs_set_res(gti->vendor_input_dev, ABS_MT_TOUCH_MAJOR, abs_major_res);
+ input_abs_set_res(gti->vendor_input_dev, ABS_MT_TOUCH_MINOR, abs_minor_res);
+ }
+
+ /*
+ * Initialize the ABS_MT_TOOL_TYPE to support touch cancel.
+ */
+ input_set_abs_params(gti->vendor_input_dev, ABS_MT_TOOL_TYPE,
+ MT_TOOL_FINGER, MT_TOOL_PALM, 0, 0);
+ }
+}
+
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->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;
@@ -2186,16 +2907,24 @@ 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;
/* Set optional operation if available. */
if (options) {
+ if (options->get_context_driver)
+ 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)
@@ -2228,6 +2957,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)
@@ -2236,6 +2967,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)
@@ -2245,21 +2978,19 @@ void goog_init_options(struct goog_touch_interface *gti,
}
}
-int goog_pm_wake_lock(struct goog_touch_interface *gti,
+int goog_pm_wake_lock_nosync(struct goog_touch_interface *gti,
enum gti_pm_wakelock_type type, bool skip_pm_resume)
{
struct gti_pm* pm = NULL;
- int ret = 0;
- bool wait_resume = false;
- if (gti == NULL)
+ if ((gti == NULL) || !gti->pm.enabled)
return -ENODEV;
pm = &gti->pm;
mutex_lock(&pm->lock_mutex);
if (pm->locks & type) {
- GOOG_DBG("unexpectedly lock: locks=0x%04X, type=0x%04X\n",
+ GOOG_DBG(gti, "unexpectedly lock: locks=0x%04X, type=0x%04X\n",
pm->locks, type);
mutex_unlock(&pm->lock_mutex);
return -EINVAL;
@@ -2279,50 +3010,48 @@ int goog_pm_wake_lock(struct goog_touch_interface *gti,
if (skip_pm_resume) {
mutex_unlock(&pm->lock_mutex);
- return ret;
+ return 0;
}
- /*
- * When triggering a wake, wait up to one second to resume.
- * SCREEN_ON does not need to wait.
- */
- if (type != GTI_PM_WAKELOCK_TYPE_SCREEN_ON)
- wait_resume = true;
-
+ pm->new_state = GTI_PM_RESUME;
+ pm->update_state = true;
+ queue_work(pm->event_wq, &pm->state_update_work);
mutex_unlock(&pm->lock_mutex);
+ return 0;
+}
+EXPORT_SYMBOL(goog_pm_wake_lock_nosync);
- /* Complete or cancel any outstanding transitions */
- cancel_work_sync(&pm->suspend_work);
- cancel_work_sync(&pm->resume_work);
-
- queue_work(pm->event_wq, &pm->resume_work);
+int goog_pm_wake_lock(struct goog_touch_interface *gti,
+ enum gti_pm_wakelock_type type, bool skip_pm_resume)
+{
+ struct gti_pm* pm = NULL;
+ int ret = 0;
- if (wait_resume) {
- wait_for_completion_timeout(&pm->bus_resumed, msecs_to_jiffies(MSEC_PER_SEC));
- if (pm->state != GTI_PM_RESUME) {
- GOOG_ERR("Failed to wake the touch bus.\n");
- ret = -ETIMEDOUT;
- }
- }
+ if ((gti == NULL) || !gti->pm.enabled)
+ return -ENODEV;
+ pm = &gti->pm;
+ ret = goog_pm_wake_lock_nosync(gti, type, skip_pm_resume);
+ if (ret < 0) return ret;
+ flush_workqueue(pm->event_wq);
return ret;
}
EXPORT_SYMBOL(goog_pm_wake_lock);
-int goog_pm_wake_unlock(struct goog_touch_interface *gti,
+int goog_pm_wake_unlock_nosync(struct goog_touch_interface *gti,
enum gti_pm_wakelock_type type)
{
struct gti_pm* pm = NULL;
int ret = 0;
- if (gti == NULL)
+ if ((gti == NULL) || !gti->pm.enabled)
return -ENODEV;
pm = &gti->pm;
mutex_lock(&pm->lock_mutex);
if (!(pm->locks & type)) {
- GOOG_DBG("unexpectedly unlock: locks=0x%04X, type=0x%04X\n",
+ GOOG_DBG(gti, "unexpectedly unlock: locks=0x%04X, type=0x%04X\n",
pm->locks, type);
mutex_unlock(&pm->lock_mutex);
return -EINVAL;
@@ -2331,25 +3060,37 @@ int goog_pm_wake_unlock(struct goog_touch_interface *gti,
pm->locks &= ~type;
if (pm->locks == 0) {
- mutex_unlock(&pm->lock_mutex);
- /* Complete or cancel any outstanding transitions */
- cancel_work_sync(&pm->suspend_work);
- cancel_work_sync(&pm->resume_work);
-
- mutex_lock(&pm->lock_mutex);
- if (pm->locks == 0)
- queue_work(pm->event_wq, &pm->suspend_work);
+ pm->new_state = GTI_PM_SUSPEND;
+ pm->update_state = true;
+ queue_work(pm->event_wq, &pm->state_update_work);
}
mutex_unlock(&pm->lock_mutex);
return ret;
}
+EXPORT_SYMBOL(goog_pm_wake_unlock_nosync);
+
+int goog_pm_wake_unlock(struct goog_touch_interface *gti,
+ enum gti_pm_wakelock_type type)
+{
+ struct gti_pm* pm = NULL;
+ int ret = 0;
+
+ if ((gti == NULL) || !gti->pm.enabled)
+ return -ENODEV;
+ pm = &gti->pm;
+
+ ret = goog_pm_wake_unlock_nosync(gti, type);
+ if (ret < 0) return ret;
+ flush_workqueue(pm->event_wq);
+ return ret;
+}
EXPORT_SYMBOL(goog_pm_wake_unlock);
bool goog_pm_wake_check_locked(struct goog_touch_interface *gti,
enum gti_pm_wakelock_type type)
{
- if (gti == NULL)
+ if ((gti == NULL) || !gti->pm.enabled)
return -ENODEV;
return gti->pm.locks & type ? true : false;
@@ -2358,73 +3099,95 @@ EXPORT_SYMBOL(goog_pm_wake_check_locked);
u32 goog_pm_wake_get_locks(struct goog_touch_interface *gti)
{
- if (gti == NULL)
+ if ((gti == NULL) || !gti->pm.enabled)
return -ENODEV;
return gti->pm.locks;
}
EXPORT_SYMBOL(goog_pm_wake_get_locks);
-static void goog_pm_suspend_work(struct work_struct *work)
+static void goog_pm_suspend(struct gti_pm *pm)
{
- struct gti_pm *pm = container_of(work, struct gti_pm, suspend_work);
struct goog_touch_interface *gti = container_of(pm,
struct goog_touch_interface, pm);
int ret = 0;
/* exit directly if device is already in suspend state */
if (pm->state == GTI_PM_SUSPEND) {
- GOOG_WARN("GTI already suspended!\n");
+ GOOG_WARN(gti, "GTI already suspended!\n");
return;
}
+
+ GOOG_INFO(gti, "irq_index: %llu, input_index: %llu.\n", gti->irq_index, gti->input_index);
pm->state = GTI_PM_SUSPEND;
- reinit_completion(&pm->bus_resumed);
if (pm->suspend)
pm->suspend(gti->vendor_dev);
if (gti->tbn_register_mask) {
ret = tbn_release_bus(gti->tbn_register_mask);
if (ret)
- GOOG_ERR("tbn_release_bus failed, ret %d!\n", ret);
+ GOOG_ERR(gti, "tbn_release_bus failed, ret %d!\n", ret);
}
+ gti_debug_hc_dump(gti);
gti_debug_input_dump(gti);
+ goog_input_release_all_fingers(gti);
+
pm_relax(gti->dev);
}
-static void goog_pm_resume_work(struct work_struct *work)
+static void goog_pm_resume(struct gti_pm *pm)
{
- struct gti_pm *pm = container_of(work, struct gti_pm, resume_work);
struct goog_touch_interface *gti = container_of(pm,
struct goog_touch_interface, pm);
int ret = 0;
/* exit directly if device isn't in suspend state */
if (pm->state == GTI_PM_RESUME) {
- GOOG_WARN("GTI already resumed!\n");
+ 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("tbn_request_bus failed, ret %d!\n", ret);
+ GOOG_ERR(gti, "tbn_request_bus failed, ret %d!\n", ret);
}
if (pm->resume)
pm->resume(gti->vendor_dev);
- complete_all(&pm->bus_resumed);
+ pm->state = GTI_PM_RESUME;
+}
+
+void goog_pm_state_update_work(struct work_struct *work) {
+ struct gti_pm *pm = container_of(work, struct gti_pm, state_update_work);
+ enum gti_pm_state new_state;
+
+ mutex_lock(&pm->lock_mutex);
+ while (pm->update_state) {
+ pm->update_state = false;
+ new_state = pm->new_state;
+ mutex_unlock(&pm->lock_mutex);
+ if (new_state != pm->state) {
+ if (new_state == GTI_PM_RESUME)
+ goog_pm_resume(pm);
+ else
+ goog_pm_suspend(pm);
+ }
+ mutex_lock(&pm->lock_mutex);
+ }
+ mutex_unlock(&pm->lock_mutex);
}
int goog_pm_register_notification(struct goog_touch_interface *gti,
const struct dev_pm_ops* ops)
{
- if (gti == NULL)
+ if ((gti == NULL) || !gti->pm.enabled)
return -ENODEV;
gti->pm.resume = ops->resume;
@@ -2435,7 +3198,7 @@ EXPORT_SYMBOL(goog_pm_register_notification);
int goog_pm_unregister_notification(struct goog_touch_interface *gti)
{
- if (gti == NULL)
+ if ((gti == NULL) || !gti->pm.enabled)
return -ENODEV;
gti->pm.resume = NULL;
@@ -2448,31 +3211,45 @@ void goog_notify_fw_status_changed(struct goog_touch_interface *gti,
enum gti_fw_status status, struct gti_fw_status_data* data)
{
switch (status) {
- case GTI_FW_STATUE_RESET:
- GOOG_LOG("Firmware has been reset\n");
+ case GTI_FW_STATUS_RESET:
+ GOOG_INFO(gti, "Firmware has been reset\n");
+ goog_input_release_all_fingers(gti);
goog_update_fw_settings(gti);
break;
- case GTI_FW_STATUE_PALM_ENTER:
- GOOG_LOG("Enter palm mode\n");
+ case GTI_FW_STATUS_PALM_ENTER:
+ GOOG_INFO(gti, "Enter palm mode\n");
+ break;
+ case GTI_FW_STATUS_PALM_EXIT:
+ GOOG_INFO(gti, "Exit palm mode\n");
break;
- case GTI_FW_STATUE_PALM_EXIT:
- GOOG_LOG("Exit palm mode\n");
+ case GTI_FW_STATUS_GRIP_ENTER:
+ GOOG_INFO(gti, "Enter grip mode\n");
break;
- case GTI_FW_STATUE_GRIP_ENTER:
- GOOG_LOG("Enter grip mode\n");
+ case GTI_FW_STATUS_GRIP_EXIT:
+ GOOG_INFO(gti, "Exit grip mode\n");
break;
- case GTI_FW_STATUE_GRIP_EXIT:
- GOOG_LOG("Exit grip mode\n");
+ 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_STATUE_NOISE_MODE:
+ 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_LOG("Noise level is changed, level: unknown\n");
+ GOOG_INFO(gti, "Noise level is changed, level: unknown\n");
} else {
if (data->noise_level == GTI_NOISE_MODE_EXIT) {
- GOOG_LOG("Exit noise mode\n");
+ GOOG_INFO(gti, "Exit noise mode\n");
+ gti->fw_status.noise_level= 0;
} else {
- GOOG_LOG("Enter noise mode, level: %d\n", data->noise_level);
+ 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:
@@ -2491,19 +3268,17 @@ static int goog_pm_probe(struct goog_touch_interface *gti)
pm->event_wq = alloc_workqueue(
"gti_pm_wq", WQ_UNBOUND | WQ_HIGHPRI | WQ_CPU_INTENSIVE, 1);
if (!pm->event_wq) {
- GOOG_ERR("Failed to create work thread for pm!\n");
+ GOOG_ERR(gti, "Failed to create work thread for pm!\n");
ret = -ENOMEM;
goto err_alloc_workqueue;
}
mutex_init(&pm->lock_mutex);
- INIT_WORK(&pm->suspend_work, goog_pm_suspend_work);
- INIT_WORK(&pm->resume_work, goog_pm_resume_work);
-
- init_completion(&pm->bus_resumed);
- complete_all(&pm->bus_resumed);
+ INIT_WORK(&pm->state_update_work, goog_pm_state_update_work);
- return ret;
+ /* init pm_qos. */
+ cpu_latency_qos_add_request(&gti->pm_qos_req, PM_QOS_DEFAULT_VALUE);
+ pm->enabled = true;
err_alloc_workqueue:
return ret;
@@ -2512,10 +3287,277 @@ err_alloc_workqueue:
static int goog_pm_remove(struct goog_touch_interface *gti)
{
struct gti_pm* pm = &gti->pm;
- if (pm->event_wq)
- destroy_workqueue(pm->event_wq);
+
+ if (pm->enabled) {
+ pm->enabled = false;
+ cpu_latency_qos_remove_request(&gti->pm_qos_req);
+ 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;
+ struct goog_touch_interface *gti = (struct goog_touch_interface *)data;
+
+ gti->irq_index++;
+ if (gti->vendor_irq_handler)
+ ret = gti->vendor_irq_handler(irq, gti->vendor_irq_cookie);
+ else
+ ret = IRQ_WAKE_THREAD;
+ gti_debug_hc_update(gti, true);
+ return ret;
+}
+
+static irqreturn_t gti_irq_thread_fn(int irq, void *data)
+{
+ int error;
+ irqreturn_t ret = IRQ_NONE;
+ struct goog_touch_interface *gti = (struct goog_touch_interface *)data;
+
+ ATRACE_BEGIN(__func__);
+
+ if (gti->tbn_enabled) {
+ error = goog_pm_wake_lock(gti, GTI_PM_WAKELOCK_TYPE_IRQ, true);
+ if (error < 0) {
+ GOOG_WARN(gti, "Skipping stray interrupt, pm state: (%d, %d)\n",
+ gti->pm.state, gti->pm.new_state);
+ ATRACE_END();
+ return IRQ_HANDLED;
+ }
+ }
+
+ 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;
+
+ goog_input_process(gti, false);
+
+ mutex_unlock(&gti->input_process_lock);
+
+ gti_debug_hc_update(gti, false);
+ cpu_latency_qos_update_request(&gti->pm_qos_req, PM_QOS_DEFAULT_VALUE);
+ if (gti->tbn_enabled)
+ goog_pm_wake_unlock_nosync(gti, GTI_PM_WAKELOCK_TYPE_IRQ);
+ ATRACE_END();
+
+ return ret;
+}
+
+int goog_devm_request_threaded_irq(struct goog_touch_interface *gti,
+ struct device *dev, unsigned int irq,
+ irq_handler_t handler, irq_handler_t thread_fn,
+ unsigned long irqflags, const char *devname,
+ void *dev_id)
+{
+ int ret;
+
+ if (gti) {
+ ret = devm_request_threaded_irq(dev, irq, gti_irq_handler, gti_irq_thread_fn,
+ irqflags, devname, gti);
+ if (dev_id)
+ gti->vendor_irq_cookie = dev_id;
+ if (handler)
+ gti->vendor_irq_handler = handler;
+ if (thread_fn)
+ gti->vendor_irq_thread_fn = thread_fn;
+ } else {
+ ret = devm_request_threaded_irq(dev, irq, handler, thread_fn,
+ irqflags, devname, dev_id);
+ }
+
+ return ret;
}
+EXPORT_SYMBOL(goog_devm_request_threaded_irq);
+
+int goog_request_threaded_irq(struct goog_touch_interface *gti,
+ unsigned int irq, irq_handler_t handler, irq_handler_t thread_fn,
+ unsigned long irqflags, const char *devname, void *dev_id)
+{
+ int ret;
+
+ if (gti) {
+ ret = request_threaded_irq(irq, gti_irq_handler, gti_irq_thread_fn,
+ irqflags, devname, gti);
+ if (dev_id)
+ gti->vendor_irq_cookie = dev_id;
+ if (handler)
+ gti->vendor_irq_handler = handler;
+ if (thread_fn)
+ gti->vendor_irq_thread_fn = thread_fn;
+ } else {
+ ret = request_threaded_irq(irq, handler, thread_fn, irqflags, devname, dev_id);
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL(goog_request_threaded_irq);
struct goog_touch_interface *goog_touch_interface_probe(
void *private_data,
@@ -2529,41 +3571,33 @@ struct goog_touch_interface *goog_touch_interface_probe(
struct goog_touch_interface *gti;
if (!dev || !input_dev || !default_handler) {
- GOOG_ERR("invalid dev/input_dev or default_handler!\n");
+ pr_err("%s: error: invalid dev/input_dev or default_handler!\n", __func__);
return NULL;
}
gti = devm_kzalloc(dev, sizeof(struct goog_touch_interface), GFP_KERNEL);
if (gti) {
- int i;
-
gti->vendor_private_data = private_data;
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;
mutex_init(&gti->input_lock);
- goog_offload_probe(gti);
- register_panel_bridge(gti);
- goog_register_tbn(gti);
- goog_init_options(gti, options);
- goog_update_fw_settings(gti);
- INIT_KFIFO(gti->debug_fifo);
- for (i = 0 ; i < MAX_SLOTS ; i++)
- gti->debug_input[i].slot = i;
- /*
- * Initialize the ABS_MT_TOOL_TYPE to support touch cancel.
- */
- input_set_abs_params(input_dev, ABS_MT_TOOL_TYPE,
- MT_TOOL_FINGER, MT_TOOL_PALM, 0, 0);
+ mutex_init(&gti->input_process_lock);
}
if (!gti_class)
- gti_class = class_create(THIS_MODULE, "goog_touch_interface");
+ 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)) {
@@ -2571,19 +3605,22 @@ struct goog_touch_interface *goog_touch_interface_probe(
gti->dev_id, gti, name);
if (gti->dev) {
gti_dev_num++;
- GOOG_LOG("device create \"%s\".\n", name);
+ GOOG_INFO(gti, "device create \"%s\".\n", name);
if (gti->vendor_dev) {
ret = sysfs_create_link(&gti->dev->kobj,
&gti->vendor_dev->kobj, "vendor");
- if (ret)
- GOOG_ERR("sysfs_create_link() failed for vendor, ret=%d!\n", ret);
+ if (ret) {
+ GOOG_ERR(gti, "sysfs_create_link() failed for vendor, ret=%d!\n",
+ ret);
+ }
}
if (gti->vendor_input_dev) {
ret = sysfs_create_link(&gti->dev->kobj,
&gti->vendor_input_dev->dev.kobj, "vendor_input");
- if (ret)
- GOOG_ERR("sysfs_create_link() failed for vendor_input, ret=%d!\n",
+ if (ret) {
+ GOOG_ERR(gti, "sysfs_create_link() failed for vendor_input, ret=%d!\n",
ret);
+ }
}
}
}
@@ -2591,11 +3628,22 @@ struct goog_touch_interface *goog_touch_interface_probe(
}
if (gti && gti->dev) {
+ goog_init_proc(gti);
+ goog_init_options(gti, options);
+ goog_offload_probe(gti);
+ /*
+ * goog_init_input() needs the offload.cap initialization by goog_offload_probe().
+ */
+ goog_init_input(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)
- GOOG_ERR("sysfs_create_group() failed, ret= %d!\n", ret);
+ GOOG_ERR(gti, "sysfs_create_group() failed, ret= %d!\n", ret);
}
return gti;
@@ -2607,34 +3655,40 @@ int goog_touch_interface_remove(struct goog_touch_interface *gti)
if (!gti)
return -ENODEV;
- if (gti->tbn_enable && gti->tbn_register_mask)
- unregister_tbn(&gti->tbn_register_mask);
-
- unregister_panel_bridge(&gti->panel_bridge);
-
- if (gti->vendor_dev)
- sysfs_remove_link(&gti->dev->kobj, "vendor");
- if (gti->vendor_input_dev)
- sysfs_remove_link(&gti->dev->kobj, "vendor_input");
+ if (gti->dev) {
+ sysfs_remove_group(&gti->dev->kobj, &goog_attr_group);
+ if (gti->vendor_dev)
+ sysfs_remove_link(&gti->dev->kobj, "vendor");
+ if (gti->vendor_input_dev)
+ sysfs_remove_link(&gti->dev->kobj, "vendor_input");
+ device_destroy(gti_class, gti->dev_id);
+ gti->dev = NULL;
+ gti_dev_num--;
+ }
if (gti_class) {
unregister_chrdev_region(gti->dev_id, 1);
- device_destroy(gti_class, gti->dev_id);
- gti_dev_num--;
+ if (!gti_dev_num) {
+ proc_remove(gti_proc_dir_root);
+ gti_proc_dir_root = NULL;
+ class_destroy(gti_class);
+ gti_class = NULL;
+ }
}
+ unregister_panel_bridge(&gti->panel_bridge);
goog_pm_remove(gti);
- gti->offload_enable = false;
- gti->v4l2_enable = false;
+ if (gti->tbn_enabled && gti->tbn_register_mask)
+ unregister_tbn(&gti->tbn_register_mask);
+
+ gti->offload_enabled = false;
+ gti->v4l2_enabled = false;
goog_offload_remove(gti);
heatmap_remove(&gti->v4l2);
devm_kfree(gti->vendor_dev, gti->heatmap_buf);
devm_kfree(gti->vendor_dev, gti);
- if (gti_class && !gti_dev_num)
- class_destroy(gti_class);
-
return 0;
}
EXPORT_SYMBOL(goog_touch_interface_remove);
diff --git a/goog_touch_interface.h b/goog_touch_interface.h
index 16a8abf..09f8245 100644
--- a/goog_touch_interface.h
+++ b/goog_touch_interface.h
@@ -12,32 +12,28 @@
#include <drm/drm_bridge.h>
#include <drm/drm_connector.h>
#include <linux/kfifo.h>
+#include <linux/pm_qos.h>
#include "heatmap.h"
#include "touch_offload.h"
#include "uapi/input/touch_offload.h"
-#if IS_ENABLED(CONFIG_VH_SYSTRACE)
-#include <trace/hooks/systrace.h>
-#else
-#define ATRACE_BEGIN(f)
-#define ATRACE_END()
-#endif
-
-#define GOOG_LOG_NAME "GTI"
-#define GOOG_DBG(fmt, args...) pr_debug("[%s] %s: " fmt, GOOG_LOG_NAME,\
+#define GTI_NAME "goog_touch_interface"
+#define GOOG_LOG_NAME(gti) ((gti && gti->dev) ? dev_name(gti->dev) : "GTI")
+#define GOOG_DBG(gti, fmt, args...) pr_debug("[%s] %s: " fmt, GOOG_LOG_NAME(gti),\
__func__, ##args)
-#define GOOG_LOG(fmt, args...) pr_info("[%s] %s: " fmt, GOOG_LOG_NAME,\
+#define GOOG_LOG(gti, fmt, args...) pr_info("[%s] " fmt, GOOG_LOG_NAME(gti), ##args)
+#define GOOG_INFO(gti, fmt, args...) pr_info("[%s] %s: " fmt, GOOG_LOG_NAME(gti),\
__func__, ##args)
-#define GOOG_WARN(fmt, args...) pr_warn("[%s] %s: " fmt, GOOG_LOG_NAME,\
+#define GOOG_WARN(gti, fmt, args...) pr_warn("[%s] %s: " fmt, GOOG_LOG_NAME(gti),\
__func__, ##args)
-#define GOOG_ERR(fmt, args...) pr_err("[%s] %s: " fmt, GOOG_LOG_NAME,\
+#define GOOG_ERR(gti, fmt, args...) pr_err("[%s] %s: " fmt, GOOG_LOG_NAME(gti),\
__func__, ##args)
#define MAX_SLOTS 10
-#define KTIME_RELEASE_ALL (ktime_set(0, 0))
#define GTI_DEBUG_KFIFO_LEN 4 /* must be power of 2. */
+#define GTI_SENSOR_2D_OUT_FORMAT_WIDTH(size) ((size > (PAGE_SIZE * sizeof(s16) / 6)) ? 1 : 5)
/*-----------------------------------------------------------------------------
* enums.
*/
@@ -51,6 +47,9 @@ enum gti_cmd_type : u32 {
/* GTI_CMD_GET operations. */
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,
@@ -59,6 +58,7 @@ enum gti_cmd_type : u32 {
GTI_CMD_GET_SCREEN_PROTECTOR_MODE,
GTI_CMD_GET_SENSING_MODE,
GTI_CMD_GET_SENSOR_DATA,
+ GTI_CMD_GET_SENSOR_DATA_MANUAL,
/* GTI_CMD_NOTIFY operations. */
GTI_CMD_NOTIFY_OPS_START = 0x300,
@@ -68,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,
@@ -83,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,
@@ -144,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 +166,19 @@ enum gti_pm_wakelock_type : u32 {
GTI_PM_WAKELOCK_TYPE_SYSFS = (1 << 3),
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),
+ GTI_PM_WAKELOCK_TYPE_FW_SETTINGS = (1 << 8),
+};
+
+enum gti_proc_type : u32 {
+ GTI_PROC_MS_BASE,
+ GTI_PROC_MS_DIFF,
+ GTI_PROC_MS_RAW,
+ GTI_PROC_SS_BASE,
+ GTI_PROC_SS_DIFF,
+ GTI_PROC_SS_RAW,
+ GTI_PROC_NUM,
};
enum gti_reset_mode : u32 {
@@ -221,18 +241,15 @@ 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_STATUE_RESET = 0,
- GTI_FW_STATUE_PALM_ENTER,
- GTI_FW_STATUE_PALM_EXIT,
- GTI_FW_STATUE_GRIP_ENTER,
- GTI_FW_STATUE_GRIP_EXIT,
- GTI_FW_STATUE_NOISE_MODE,
+ 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,
};
enum gti_noise_mode_level : u8 {
@@ -246,21 +263,76 @@ enum gti_noise_mode_level : u8 {
* Structures.
*/
+struct gti_context_changed {
+ union {
+ struct {
+ u32 screen_state : 1;
+ u32 display_refresh_rate : 1;
+ u32 touch_report_rate : 1;
+ u32 noise_state : 1;
+ u32 water_mode : 1;
+ u32 charger_state : 1;
+ u32 hinge_angle : 1;
+ u32 offload_timestamp : 1;
+ };
+ u32 value;
+ };
+};
+
+struct gti_context_driver_cmd {
+ struct gti_context_changed context_changed;
+
+ u8 screen_state;
+ u8 display_refresh_rate;
+ u8 touch_report_rate;
+ u8 noise_state;
+ u8 water_mode;
+ u8 charger_state;
+ s16 hinge_angle;
+
+ ktime_t offload_timestamp;
+};
+
+struct gti_context_stylus_cmd {
+ struct {
+ u32 coords : 1;
+ u32 coords_timestamp : 1;
+ u32 pen_paired : 1;
+ u32 pen_active : 1;
+ } contents;
+ struct TouchOffloadCoord pen_offload_coord;
+ ktime_t pen_offload_coord_timestamp;
+ u8 pen_paired;
+ u8 pen_active;
+};
+
struct gti_continuous_report_cmd {
enum gti_continuous_report_setting setting;
};
struct gti_debug_coord {
ktime_t time;
+ u64 irq_index;
struct TouchOffloadCoord coord;
};
+struct gti_debug_health_check {
+ ktime_t irq_time;
+ u64 irq_index;
+ u64 input_index;
+ unsigned long slot_bit_active;
+};
+
struct gti_debug_input {
int slot;
struct gti_debug_coord pressed;
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;
};
@@ -293,6 +365,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;
};
@@ -322,7 +398,10 @@ struct gti_sensor_data_cmd {
/**
* struct gti_union_cmd_data - GTI commands to vendor driver.
+ * @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.
@@ -331,15 +410,20 @@ 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.
* @selftest_cmd: command to do self-test.
* @sensing_cmd: command to set/set sensing mode.
* @sensor_data_cmd: command to get sensor data.
+ * @manual_sensor_data_cmd: command to get sensor data manually.
*/
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;
@@ -348,12 +432,14 @@ 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;
struct gti_selftest_cmd selftest_cmd;
struct gti_sensing_cmd sensing_cmd;
struct gti_sensor_data_cmd sensor_data_cmd;
+ struct gti_sensor_data_cmd manual_sensor_data_cmd;
};
/**
@@ -362,10 +448,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.
@@ -381,22 +471,28 @@ 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.
*/
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);
@@ -405,36 +501,41 @@ 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);
};
/**
* struct gti_pm - power manager for GTI.
- * @suspend_work: a work to run suspend.
- * @resume_work: a work to run resume.
+ * @state_update_work: a work to update pm state.
* @event_wq: a work queue to run suspend/resume work.
- * @bus_resumed: a completion for waiting for resume is done.
* @locks: the lock state.
* @lock_mutex: protect the lock state.
* @state: GTI pm state.
+ * @new_state: New GTI pm state to be updated to.
+ * @enabled: Boolean value to represent if GTI PM is active.
+ * @update_state: Boolean value if state needs to be updated.
* @resume: callback for notifying resume.
* @suspend: callback for notifying suspend.
*/
struct gti_pm {
- struct work_struct suspend_work;
- struct work_struct resume_work;
+ struct work_struct state_update_work;
struct workqueue_struct *event_wq;
- struct completion bus_resumed;
u32 locks;
struct mutex lock_mutex;
enum gti_pm_state state;
+ enum gti_pm_state new_state;
+ bool enabled;
+ bool update_state;
int (*resume)(struct device *dev);
int (*suspend)(struct device *dev);
@@ -448,28 +549,50 @@ struct gti_pm {
* @dev: pointer to struct device that used by google touch interface driver.
* @options: optional configuration that could apply by vendor driver.
* @input_lock: protect the input report between non-offload and offload.
+ * @input_process_lock: protect heatmap reading and frame reserving.
* @offload: struct that used by touch offload.
* @offload_frame: reserved frame that used by touch offload.
* @v4l2: struct that used by v4l2.
* @panel_bridge: struct that used to register panel bridge notification.
* @connector: struct that used to get panel status.
* @cmd: struct that used by vendor default handler.
+ * @proc_dir: struct that used for procfs.
+ * @proc_heatmap: struct that used for heatmap procfs.
* @input_timestamp: input timestamp from touch vendor driver.
* @mf_downtime: timestamp for motion filter control.
* @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.
- * @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.
- * @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.
* @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.
@@ -478,10 +601,19 @@ 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.
+ * @vendor_irq_thread_fn: irq thread function that register by vendor driver.
+ * @vendor_irq_cookie: irq cookie that register by vendor driver.
* @vendor_default_handler: touch vendor driver default operation.
- * @released_count: finger up count.
+ * @released_index: finger up count.
* @debug_input: struct that used to debug input.
- * @debug_fifo: struct that used to debug input.
+ * @debug_fifo_input: kfifo struct to track recent coordinate report for input debug.
+ * @debug_hc: struct that used for the health check.
+ * @debug_fifo_hc: kfifo struct to track recent touch interrupt information for health check.
*/
struct goog_touch_interface {
@@ -491,33 +623,58 @@ struct goog_touch_interface {
struct device *dev;
struct gti_optional_configuration options;
struct mutex input_lock;
+ struct mutex input_process_lock;
struct touch_offload_context offload;
struct touch_offload_frame *offload_frame;
struct v4l2_heatmap v4l2;
struct drm_bridge panel_bridge;
struct drm_connector *connector;
struct gti_union_cmd_data cmd;
+ struct proc_dir_entry *proc_dir;
+ struct proc_dir_entry *proc_heatmap[GTI_PROC_NUM];
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;
enum gti_mf_state mf_state;
enum gti_screen_protector_mode screen_protector_mode_setting;
u32 tbn_register_mask;
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 force_legacy_report;
- bool offload_enable;
- bool v4l2_enable;
- bool tbn_enable;
+ 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;
union {
- u8 offload_id_byte[4];
- u32 offload_id;
+ u8 offload_id_byte[4];
+ u32 offload_id;
};
u8 *heatmap_buf;
u32 heatmap_buf_size;
@@ -527,19 +684,30 @@ 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;
+ irq_handler_t vendor_irq_thread_fn;
+ void *vendor_irq_cookie;
+
int (*vendor_default_handler)(void *private_data,
enum gti_cmd_type cmd_type, struct gti_union_cmd_data *cmd);
/* Debug used. */
- unsigned long released_count;
+ u64 released_index;
struct gti_debug_input debug_input[MAX_SLOTS];
- DECLARE_KFIFO(debug_fifo, struct gti_debug_input, GTI_DEBUG_KFIFO_LEN);
+ DECLARE_KFIFO(debug_fifo_input, struct gti_debug_input, GTI_DEBUG_KFIFO_LEN);
+ struct gti_debug_health_check debug_hc;
+ DECLARE_KFIFO(debug_fifo_hc, struct gti_debug_health_check, GTI_DEBUG_KFIFO_LEN);
};
/*-----------------------------------------------------------------------------
* Forward declarations.
*/
-
+inline bool goog_check_spi_dma_enabled(struct spi_device *spi_dev);
inline bool goog_input_legacy_report(struct goog_touch_interface *gti);
inline void goog_input_lock(struct goog_touch_interface *gti);
inline void goog_input_unlock(struct goog_touch_interface *gti);
@@ -559,9 +727,17 @@ inline void goog_input_report_key(
struct goog_touch_interface *gti,
struct input_dev *dev, unsigned int code, int value);
inline void goog_input_sync(struct goog_touch_interface *gti, struct input_dev *dev);
+inline int goog_devm_request_threaded_irq(struct goog_touch_interface *gti,
+ struct device *dev, unsigned int irq,
+ irq_handler_t handler, irq_handler_t thread_fn,
+ unsigned long irqflags, const char *devname,
+ void *dev_id);
+inline int goog_request_threaded_irq(struct goog_touch_interface *gti,
+ unsigned int irq, irq_handler_t handler, irq_handler_t thread_fn,
+ 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);
+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,
@@ -571,8 +747,12 @@ struct goog_touch_interface *goog_touch_interface_probe(
struct gti_optional_configuration *options);
int goog_touch_interface_remove(struct goog_touch_interface *gti);
+int goog_pm_wake_lock_nosync(struct goog_touch_interface *gti,
+ enum gti_pm_wakelock_type type, bool skip_pm_resume);
int goog_pm_wake_lock(struct goog_touch_interface *gti,
enum gti_pm_wakelock_type type, bool skip_pm_resume);
+int goog_pm_wake_unlock_nosync(struct goog_touch_interface *gti,
+ enum gti_pm_wakelock_type type);
int goog_pm_wake_unlock(struct goog_touch_interface *gti,
enum gti_pm_wakelock_type type);
bool goog_pm_wake_check_locked(struct goog_touch_interface *gti,
@@ -584,5 +764,10 @@ int goog_pm_unregister_notification(struct goog_touch_interface *gti);
void goog_notify_fw_status_changed(struct goog_touch_interface *gti,
enum gti_fw_status status, struct gti_fw_status_data* data);
+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/goog_touch_interface_nop.h b/goog_touch_interface_nop.h
index 4483749..0528e37 100644
--- a/goog_touch_interface_nop.h
+++ b/goog_touch_interface_nop.h
@@ -9,8 +9,6 @@
#include <linux/input/mt.h>
-#define KTIME_RELEASE_ALL (ktime_set(0, 0))
-
enum gti_cmd_type : u32{
GTI_CMD_NOP,
};
diff --git a/heatmap.c b/heatmap.c
index 679e7f6..85a5f65 100644
--- a/heatmap.c
+++ b/heatmap.c
@@ -380,6 +380,9 @@ int heatmap_probe(struct v4l2_heatmap *v4l2)
return 0;
err_video_device_release:
+ mutex_lock(&v4l2->lock);
+ vb2_queue_release(&v4l2->queue);
+ mutex_unlock(&v4l2->lock);
video_device_release(&v4l2->vdev);
err_unreg_v4l2:
@@ -395,6 +398,11 @@ void heatmap_remove(struct v4l2_heatmap *v4l2)
{
if (v4l2->frame) {
video_unregister_device(&v4l2->vdev);
+
+ mutex_lock(&v4l2->lock);
+ vb2_queue_release(&v4l2->queue);
+ mutex_unlock(&v4l2->lock);
+
v4l2_device_unregister(&v4l2->device);
devm_kfree(v4l2->parent_dev, v4l2->frame);
v4l2->frame = NULL;
diff --git a/heatmap.h b/heatmap.h
index cc7a9da..21ddbd0 100644
--- a/heatmap.h
+++ b/heatmap.h
@@ -1,5 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _HEATMAP_H_
+#define _HEATMAP_H_
+
#include <media/v4l2-device.h>
#include <media/v4l2-ioctl.h>
#include <media/videobuf2-v4l2.h>
@@ -52,4 +55,6 @@ void heatmap_remove(struct v4l2_heatmap *v4l2);
* This function should be called from the driver. Internally, it will call
* read_frame(..) provided by the driver to read the actual data.
*/
-void heatmap_read(struct v4l2_heatmap *v4l2, uint64_t timestamp); \ No newline at end of file
+void heatmap_read(struct v4l2_heatmap *v4l2, uint64_t timestamp);
+
+#endif // _HEATMAP_H_
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 375095a..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,44 +186,87 @@ 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);
if (wait_for_completion_timeout(wait_for_completion,
- msecs_to_jiffies(timeout)) == 0) {
- dev_err(tbn->dev, "AP %s bus ... timeout!, aoc2ap_gpio=%d\n",
- msg, gpio_get_value(tbn->aoc2ap_gpio));
+ msecs_to_jiffies(timeout)) == 0) {
+ int ap2aoc_val = gpio_get_value(tbn->ap2aoc_gpio);
+ int aoc2ap_val = gpio_get_value(tbn->aoc2ap_gpio);
+
complete_all(wait_for_completion);
- ret = -ETIMEDOUT;
+ if (bus_owner == aoc2ap_val)
+ ret = 0;
+ else
+ ret = -ETIMEDOUT;
+ dev_err(tbn->dev, "AP %s bus ... timeout!, ap2aoc_gpio(B:%d,A:%d)"
+ " aoc2ap_gpio(B:%d,A:%d), ret=%d\n",
+ msg, ap2aoc_val_org, ap2aoc_val, aoc2ap_val_org,
+ aoc2ap_val, ret);
} 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;
@@ -128,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;
@@ -140,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)
@@ -168,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",
@@ -187,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;
@@ -227,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,
@@ -252,6 +425,11 @@ static int tbn_probe(struct platform_device *pdev)
__func__, tbn->ap2aoc_gpio, err);
goto failed;
}
+ } else {
+ dev_err(tbn->dev, "%s: invalid ap2aoc_gpio %d!\n",
+ __func__, tbn->ap2aoc_gpio);
+ err = -EPROBE_DEFER;
+ goto failed;
}
tbn->aoc2ap_gpio = of_get_named_gpio(np, "tbn,aoc2ap_gpio", 0);
@@ -279,10 +457,35 @@ static int tbn_probe(struct platform_device *pdev)
} else {
dev_err(tbn->dev, "%s: invalid aoc2ap_gpio %d!\n",
__func__, tbn->aoc2ap_gpio);
+ 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);
@@ -292,26 +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) {
+ 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 393f247..344b6ae 100644
--- a/touch_offload.c
+++ b/touch_offload.c
@@ -326,7 +326,7 @@ static int touch_offload_allocate_buffers(struct touch_offload_context *context,
if (!(context->config.context_channel_types & mask))
continue;
- frame->channel_type[chan] = mask;
+ frame->channel_type[chan] = (__u32)mask;
size = 0;
switch (mask) {
case CONTEXT_CHANNEL_TYPE_DRIVER_STATUS:
@@ -338,7 +338,7 @@ static int touch_offload_allocate_buffers(struct touch_offload_context *context,
TOUCH_OFFLOAD_FRAME_SIZE_STYLUS_STATUS;
break;
default:
- pr_err("%s: Invalid channel_type = 0x%08X",
+ pr_err("%s: Invalid channel_type = 0x%08X\n",
__func__, mask);
goto invalid_context_channel;
}
@@ -350,7 +350,7 @@ static int touch_offload_allocate_buffers(struct touch_offload_context *context,
chan_header =
(struct TouchOffloadChannelHeader *)
frame->channel_data[chan];
- chan_header->channel_type = mask;
+ chan_header->channel_type = (__u32)mask;
chan_header->channel_size = size;
frame->channel_data_size[chan] = size;
frame->header.frame_size += size;
@@ -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;
@@ -657,8 +659,6 @@ int touch_offload_init(struct touch_offload_context *context)
{
int ret = 0;
- pr_debug("%s\n", __func__);
-
/* Initialize ioctl interface */
context->file_in_use = false;
mutex_init(&context->file_lock);
@@ -675,40 +675,53 @@ int touch_offload_init(struct touch_offload_context *context)
init_completion(&context->reserve_returned);
complete_all(&context->reserve_returned);
- if (!context->multiple_panels)
- scnprintf(context->device_name, 32, "%s", DEVICE_NAME);
+ if (!strnlen(context->device_name, sizeof(context->device_name)))
+ scnprintf(context->device_name, sizeof(context->device_name), "%s", DEVICE_NAME);
+
+ pr_info("%s: %s.\n", __func__, context->device_name);
/* Initialize char device */
- context->major_num = register_chrdev(0, context->device_name,
- &touch_offload_fops);
- if (context->major_num < 0) {
+ cdev_init(&context->dev, &touch_offload_fops);
+
+ ret = alloc_chrdev_region(&context->dev_num, 0, 1, context->device_name);
+ if (ret < 0) {
pr_err("%s: register_chrdev failed with error = %u\n",
- __func__, context->major_num);
- return context->major_num;
+ __func__, ret);
+ return ret;
+ }
+
+ ret = cdev_add(&context->dev, context->dev_num, 1);
+ if (ret < 0) {
+ pr_err("%s: cdev_add failed with error = %u\n",
+ __func__, ret);
+ goto err_cdev_add;
}
context->cls = class_create(THIS_MODULE, context->device_name);
if (IS_ERR(context->cls)) {
pr_err("%s: class_create failed with error = %ld.\n",
__func__, PTR_ERR(context->cls));
- unregister_chrdev(context->major_num, context->device_name);
- return PTR_ERR(context->cls);
+ ret = PTR_ERR(context->cls);
+ goto err_class_create;
}
- context->device = device_create(context->cls, NULL,
- MKDEV(context->major_num, 0), NULL,
- context->device_name);
+ context->device = device_create(context->cls, NULL, context->dev_num,
+ NULL, context->device_name);
if (IS_ERR(context->device)) {
pr_err("%s: device_create failed with error = %ld.\n",
__func__, PTR_ERR(context->device));
- class_destroy(context->cls);
- unregister_chrdev(context->major_num, context->device_name);
- return PTR_ERR(context->device);
+ ret = PTR_ERR(context->device);
+ goto err_device_create;
}
- cdev_init(&context->dev, &touch_offload_fops);
- cdev_add(&context->dev, MKDEV(context->major_num, 0), 1);
+ return ret;
+err_device_create:
+ class_destroy(context->cls);
+err_class_create:
+ cdev_del(&context->dev);
+err_cdev_add:
+ unregister_chrdev_region(context->dev_num, 1);
return ret;
}
EXPORT_SYMBOL(touch_offload_init);
@@ -717,13 +730,13 @@ int touch_offload_cleanup(struct touch_offload_context *context)
{
pr_debug("%s\n", __func__);
- cdev_del(&context->dev);
-
- device_destroy(context->cls, MKDEV(context->major_num, 0));
+ device_destroy(context->cls, context->dev_num);
class_destroy(context->cls);
- unregister_chrdev(context->major_num, context->device_name);
+ cdev_del(&context->dev);
+
+ unregister_chrdev_region(context->dev_num, 1);
complete_all(&context->reserve_returned);
diff --git a/touch_offload.h b/touch_offload.h
index 2d97d21..0f9f0b6 100644
--- a/touch_offload.h
+++ b/touch_offload.h
@@ -36,7 +36,7 @@ struct touch_offload_frame {
/* Touch Offload Context
*
* dev - char device
- * major_num - device major number
+ * dev_num - device number
* cls - pointer to class associated class
* device - pointer to associated device
* file - char device file for ioctl interface
@@ -61,13 +61,13 @@ struct touch_offload_frame {
struct touch_offload_context {
/* ioctl interface */
struct cdev dev;
- int major_num;
+ dev_t dev_num;
struct class *cls;
struct device *device;
struct file file;
struct mutex file_lock;
bool file_in_use;
- bool multiple_panels;
+ bool multiple_panels; /* TODO(b/201610482): remove this variable later! */
char device_name[32];
/* touch capabilities */