summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWill McVicker <willmcvicker@google.com>2022-04-14 12:14:26 -0700
committerWill McVicker <willmcvicker@google.com>2022-04-14 12:14:26 -0700
commita243325c2aa6e3219cb08596000b5e2a471dda31 (patch)
treedfbd462920c4a6aa0df0bf1f4e848a4fea925a65
parentbe6ba854f8a96a4c820db65715747d711e2e80b4 (diff)
parentb85fd5939c20d5cbac45ab426a94aca730d7342a (diff)
downloadsec_touch-a243325c2aa6e3219cb08596000b5e2a471dda31.tar.gz
Merge 'android13-gs-pixel-5.10' into android-gs-pixel-mainline
* 'android13-gs-pixel-5.10' of sso://partner-android/kernel/private/google-modules/touch/sec_touch: touch/sec: update FW grip with offload filter_grip setting. touch: sec: support rotation reporting touch/sec: add more logs after touch suspend. touch/sec: enable FW grip for wake-up gesture. touch/sec: abandon the cancel event for FoD. touch/sec: Configure grip prescreen mode with timeout. Kleaf: add touch sec kernel module for cloudripper touch/sec: use mode switch for resume insted of T-IC reset. touch/sec: support FoD (Fingerprint on Display) event. touch/sec: support FoD (Fingerprint on Display) coordinates. touch/sec: add bugreport bus reference. touch/sec: Revise heatmap retrieval for v4l2. touch/sec: set rt priority for SPI transfer touch/sec: defer probe if FW initialization failed touch/sec: refine input timestamp for normal report touch/sec: defer probe if boot ack timeout touch: sec: add mutex to protect offload report touch/sec: Single read command for customlib. touch/sec: Reduce heatmap enable read commands. touch/sec: Add delay to read_from_customlib. touch: sec: tbn function changes touch/sec_ts: Do not get properties of non-existent supplies touch/sec: Update SPI delay for reading data in custom library. touch/sec: handle the specific cases to force WLC mode touch/sec: add tsp_vsync status touch/sec: look at display effectively active state touch/sec: Revise SPI delay for reading encoded heatmap. touch/sec: use hardware reset to re-initialize touch touch/sec: Dynamic SPI delay for reading data in custom library. touch/sec: support encoded heatmap in custom library. input: touchscreen: sec: Read touch_offload device_id from DT. touch/sec: use corresponding debug flag for logs touch/sec: support major and minor conversion touch/sec: add more information into status sysfs touch/sec: update touch_offload include path and Makefile touch/sec: add sysfs to support heatmap dump touch/sec: Fix -Wtautological-unsigned-zero-compare warnings touch/sec: update heatmap include path and Makefile touch/sec: update include path and Makefile for the TBN driver Signed-off-by: Will McVicker <willmcvicker@google.com> Change-Id: Ic91a89a3e4c96a722ed84316cbf2791fd12cc62a
-rw-r--r--BUILD.bazel31
-rw-r--r--Makefile17
-rw-r--r--sec_ts.c1399
-rw-r--r--sec_ts.h142
-rw-r--r--sec_ts_fn.c321
-rw-r--r--sec_ts_fw.c203
-rw-r--r--sec_ts_only_vendor.c2
7 files changed, 1675 insertions, 440 deletions
diff --git a/BUILD.bazel b/BUILD.bazel
new file mode 100644
index 0000000..37eb754
--- /dev/null
+++ b/BUILD.bazel
@@ -0,0 +1,31 @@
+# NOTE: THIS FILE IS EXPERIMENTAL FOR THE BAZEL MIGRATION AND NOT USED FOR
+# YOUR BUILDS CURRENTLY.
+#
+# It is not yet the source of truth for your build. If you're looking to modify
+# the build file, modify the Android.bp file instead. Do *not* modify this file
+# unless you have coordinated with the team managing the Soong to Bazel
+# migration.
+
+load("//build/kleaf:kernel.bzl", "kernel_module")
+
+kernel_module(
+ name = "sec.cloudripper",
+ srcs = glob([
+ "**/*.c",
+ "**/*.h",
+ "Kbuild",
+ ]) + [
+ "//private/google-modules/touch/common:headers",
+ "//private/google-modules/display/samsung:headers",
+ ],
+ outs = [
+ "sec_touch.ko",
+ ],
+ kernel_build = "//private/gs-google:cloudripper",
+ kernel_module_deps = [
+ "//private/google-modules/touch/common:common.cloudripper",
+ ],
+ visibility = [
+ "//private/gs-google:__pkg__",
+ ],
+)
diff --git a/Makefile b/Makefile
index 7c7677c..87d6e92 100644
--- a/Makefile
+++ b/Makefile
@@ -4,8 +4,19 @@ else
obj-$(CONFIG_TOUCHSCREEN_SEC_TS) += sec_ts.o sec_ts_fw.o sec_ts_fn.o sec_cmd.o sec_ts_only_vendor.o
endif
-KBUILD_OPTIONS += CONFIG_TOUCHSCREEN_SEC_TS=m
-EXTRA_CFLAGS = -I$(KERNEL_SRC)/../google-modules/display
+KBUILD_OPTIONS += CONFIG_TOUCHSCREEN_SEC_TS=m
+EXTRA_CFLAGS += -DDYNAMIC_DEBUG_MODULE
+EXTRA_CFLAGS += -DCONFIG_TOUCHSCREEN_TBN
+EXTRA_CFLAGS += -DCONFIG_TOUCHSCREEN_HEATMAP
+EXTRA_CFLAGS += -DCONFIG_TOUCHSCREEN_OFFLOAD
+EXTRA_CFLAGS += -I$(KERNEL_SRC)/../google-modules/display
+EXTRA_CFLAGS += -I$(KERNEL_SRC)/../google-modules/touch/common
+EXTRA_CFLAGS += -I$(KERNEL_SRC)/../google-modules/touch/common/include
+EXTRA_SYMBOLS += $(OUT_DIR)/../google-modules/touch/common/Module.symvers
modules modules_install clean:
- $(MAKE) -C $(KERNEL_SRC) M=$(M) $(KBUILD_OPTIONS) EXTRA_CFLAGS="$(EXTRA_CFLAGS)" $(@)
+ $(MAKE) -C $(KERNEL_SRC) M=$(M) \
+ $(KBUILD_OPTIONS) \
+ EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \
+ KBUILD_EXTRA_SYMBOLS="$(EXTRA_SYMBOLS)" \
+ $(@)
diff --git a/sec_ts.c b/sec_ts.c
index 77b68eb..20a9fda 100644
--- a/sec_ts.c
+++ b/sec_ts.c
@@ -15,6 +15,11 @@ struct sec_ts_data *tsp_info;
#include "sec_ts.h"
#include <samsung/exynos_drm_connector.h>
+/* init the kfifo for debug used. */
+#define SEC_TS_DEBUG_KFIFO_LEN 4 /* must be power of 2. */
+DEFINE_KFIFO(debug_fifo, struct sec_ts_coordinate, SEC_TS_DEBUG_KFIFO_LEN);
+static struct sec_ts_coordinate last_coord[SEC_TS_DEBUG_KFIFO_LEN];
+
/* Switch GPIO values */
#define SEC_SWITCH_GPIO_VALUE_SLPI_MASTER 1
#define SEC_SWITCH_GPIO_VALUE_AP_MASTER 0
@@ -47,29 +52,45 @@ static void unregister_panel_bridge(struct drm_bridge *bridge);
int sec_ts_read_information(struct sec_ts_data *ts);
#ifndef I2C_INTERFACE
-int sec_ts_spi_delay(u8 reg)
+u32 sec_ts_spi_delay(u8 reg, u32 data_len)
{
+ u32 delay_us = 100;
+
switch (reg) {
case SEC_TS_READ_TOUCH_RAWDATA:
- return 500;
+ delay_us = 500;
+ break;
#if IS_ENABLED(CONFIG_TOUCHSCREEN_HEATMAP)
case SEC_TS_CMD_HEATMAP_READ:
- return 500;
+ delay_us = 500;
+ break;
#endif
+ case SEC_TS_CMD_CUSTOMLIB_READ_PARAM:
+ delay_us = min(120 + (data_len >> 2), (u32) 500);
+ break;
case SEC_TS_READ_ALL_EVENT:
- return 550;
+ delay_us = 550;
+ break;
case SEC_TS_READ_CSRAM_RTDP_DATA:
- return 550;
+ delay_us = 550;
+ break;
case SEC_TS_CAAT_READ_STORED_DATA:
- return 550;
+ delay_us = 550;
+ break;
case SEC_TS_CMD_FLASH_READ_DATA:
- return 2000;
+ delay_us = 2000;
+ break;
case SEC_TS_READ_FIRMWARE_INTEGRITY:
- return 20*1000;
+ delay_us = 20*1000;
+ break;
case SEC_TS_READ_SELFTEST_RESULT:
- return 4000;
- default: return 100;
+ delay_us = 4000;
+ break;
}
+
+ usleep_range(delay_us, delay_us + 1);
+
+ return delay_us;
}
int sec_ts_spi_post_delay(u8 reg)
@@ -101,7 +122,7 @@ int sec_ts_write(struct sec_ts_data *ts, u8 reg, u8 *data, int len)
if (ts->power_status == SEC_TS_STATE_POWER_OFF) {
input_err(true, &ts->client->dev,
- "%s: POWER_STATUS : OFF\n", __func__);
+ "%s: POWER_STATUS: OFF\n", __func__);
goto err;
}
@@ -182,7 +203,7 @@ int sec_ts_write(struct sec_ts_data *ts, u8 reg, u8 *data, int len)
if (ts->power_status == SEC_TS_STATE_POWER_OFF) {
input_err(true, &ts->client->dev,
- "%s: POWER_STATUS : OFF, retry:%d\n",
+ "%s: POWER_STATUS: OFF, retry: %d\n",
__func__, retry);
mutex_unlock(&ts->io_mutex);
goto err;
@@ -231,6 +252,7 @@ static int sec_ts_read_internal(struct sec_ts_data *ts, u8 reg,
#else
struct spi_message msg;
struct spi_transfer transfer[1] = { { 0 } };
+ u32 spi_delay_us = 0;
unsigned int i;
unsigned int spi_write_len = 0, spi_read_len = 0;
unsigned char write_checksum = 0x0, read_checksum = 0x0;
@@ -240,7 +262,7 @@ static int sec_ts_read_internal(struct sec_ts_data *ts, u8 reg,
if (ts->power_status == SEC_TS_STATE_POWER_OFF) {
input_err(true, &ts->client->dev,
- "%s: POWER_STATUS : OFF\n", __func__);
+ "%s: POWER_STATUS: OFF\n", __func__);
goto err;
}
@@ -311,7 +333,7 @@ static int sec_ts_read_internal(struct sec_ts_data *ts, u8 reg,
usleep_range(1 * 1000, 1 * 1000);
if (ts->power_status == SEC_TS_STATE_POWER_OFF) {
input_err(true, &ts->client->dev,
- "%s: POWER_STATUS : OFF, retry:%d\n",
+ "%s: POWER_STATUS: OFF, retry: %d\n",
__func__, retry);
mutex_unlock(&ts->io_mutex);
goto err;
@@ -356,7 +378,7 @@ static int sec_ts_read_internal(struct sec_ts_data *ts, u8 reg,
if (ts->power_status ==
SEC_TS_STATE_POWER_OFF) {
input_err(true, &ts->client->dev,
- "%s: POWER_STATUS : OFF, retry:%d\n",
+ "%s: POWER_STATUS: OFF, retry: %d\n",
__func__, retry);
mutex_unlock(&ts->io_mutex);
goto err;
@@ -372,8 +394,7 @@ static int sec_ts_read_internal(struct sec_ts_data *ts, u8 reg,
continue;
}
- usleep_range(sec_ts_spi_delay(reg),
- sec_ts_spi_delay(reg) + 1);
+ spi_delay_us = sec_ts_spi_delay(reg, len);
// read sequence start
spi_message_init(&msg);
@@ -411,16 +432,29 @@ static int sec_ts_read_internal(struct sec_ts_data *ts, u8 reg,
ret = -EIO;
- input_err(true, &ts->client->dev,
- "%s: retry %d\n",
- __func__, retry + 1);
- ts->comm_err_count++;
+ /*
+ * For LP idle state from AOD to normal screen-on,
+ * T-IC needs one SPI cmds to wake-up.
+ * Therefore, change the log level to warning
+ * for this intended behavir.
+ */
+ if (!completion_done(&ts->bus_resumed) &&
+ reg == SEC_TS_CMD_CHG_SYSMODE) {
+ dev_warn(&ts->client->dev,
+ "%s: wake-up touch(#%d) by 0x%02X cmd delay_us(%d)\n",
+ __func__, retry + 1, reg, spi_delay_us);
+ } else {
+ input_err(true, &ts->client->dev,
+ "%s: retry %d for 0x%02X size(%d) delay_us(%d)\n",
+ __func__, retry + 1, reg, len, spi_delay_us);
+ ts->comm_err_count++;
+ }
usleep_range(1 * 1000, 1 * 1000);
if (ts->power_status ==
SEC_TS_STATE_POWER_OFF) {
input_err(true, &ts->client->dev,
- "%s: POWER_STATUS : OFF, retry:%d\n",
+ "%s: POWER_STATUS: OFF, retry: %d\n",
__func__, retry);
mutex_unlock(&ts->io_mutex);
goto err;
@@ -451,7 +485,7 @@ static int sec_ts_read_internal(struct sec_ts_data *ts, u8 reg,
usleep_range(1 * 1000, 1 * 1000);
if (ts->power_status == SEC_TS_STATE_POWER_OFF) {
input_err(true, &ts->client->dev,
- "%s: POWER_STATUS : OFF, retry:%d\n",
+ "%s: POWER_STATUS: OFF, retry: %d\n",
__func__, retry);
mutex_unlock(&ts->io_mutex);
goto err;
@@ -482,7 +516,7 @@ static int sec_ts_read_internal(struct sec_ts_data *ts, u8 reg,
if (ts->power_status ==
SEC_TS_STATE_POWER_OFF) {
input_err(true, &ts->client->dev,
- "%s: POWER_STATUS : OFF, retry:%d\n",
+ "%s: POWER_STATUS: OFF, retry: %d\n",
__func__, retry);
mutex_unlock(&ts->io_mutex);
goto err;
@@ -527,7 +561,7 @@ static int sec_ts_read_internal(struct sec_ts_data *ts, u8 reg,
if (ts->power_status ==
SEC_TS_STATE_POWER_OFF) {
input_err(true, &ts->client->dev,
- "%s: POWER_STATUS : OFF, retry:%d\n",
+ "%s: POWER_STATUS: OFF, retry: %d\n",
__func__, retry);
mutex_unlock(&ts->io_mutex);
goto err;
@@ -543,8 +577,7 @@ static int sec_ts_read_internal(struct sec_ts_data *ts, u8 reg,
continue;
}
- usleep_range(sec_ts_spi_delay(reg),
- sec_ts_spi_delay(reg) + 1);
+ sec_ts_spi_delay(reg, len);
copy_size = 0;
remain = spi_read_len;
@@ -595,7 +628,7 @@ static int sec_ts_read_internal(struct sec_ts_data *ts, u8 reg,
== SEC_TS_STATE_POWER_OFF) {
input_err(true,
&ts->client->dev,
- "%s: POWER_STATUS : OFF, retry:%d\n",
+ "%s: POWER_STATUS: OFF, retry: %d\n",
__func__, retry);
mutex_unlock(&ts->io_mutex);
goto err;
@@ -669,10 +702,15 @@ skip_spi_read:
} else
ts->io_err_count = 0;
- /* do hw reset if continuously failed over SEC_TS_IO_RESET_CNT times */
- if (ts->io_err_count >= SEC_TS_IO_RESET_CNT) {
+ /*
+ * Do hw reset if continuously failed over SEC_TS_IO_RESET_CNT times
+ * except for FW update process.
+ */
+ if (ts->io_err_count >= SEC_TS_IO_RESET_CNT &&
+ (ts->bus_refmask & SEC_TS_BUS_REF_FW_UPDATE) == 0) {
+ ts->hw_reset_count++;
ts->io_err_count = 0;
- sec_ts_hw_reset(ts);
+ sec_ts_system_reset(ts, RESET_MODE_HW, false, true);
}
return ret;
@@ -884,7 +922,7 @@ retry_message:
usleep_range(1 * 1000, 1 * 1000);
if (ts->power_status == SEC_TS_STATE_POWER_OFF) {
input_err(true, &ts->client->dev,
- "%s: POWER_STATUS : OFF, retry:%d\n",
+ "%s: POWER_STATUS: OFF, retry: %d\n",
__func__, retry);
mutex_unlock(&ts->io_mutex);
goto err;
@@ -965,7 +1003,9 @@ static int sec_ts_read_from_customlib(struct sec_ts_data *ts, u8 *data, int len)
ret = sec_ts_write(ts, SEC_TS_CMD_CUSTOMLIB_READ_PARAM, data, 2);
if (ret < 0)
input_err(true, &ts->client->dev,
- "%s: fail to read custom library command\n", __func__);
+ "%s: fail to write custom library command\n", __func__);
+
+ usleep_range(100, 100);
ret = sec_ts_read(ts, SEC_TS_CMD_CUSTOMLIB_READ_PARAM, (u8 *)data, len);
if (ret < 0)
@@ -1094,7 +1134,7 @@ int sec_ts_read_calibration_report(struct sec_ts_data *ts)
}
input_info(true, &ts->client->dev,
- "%s: count:%d, pass count:%d, fail count:%d, status:%X, param version:%X %X %X %X\n",
+ "%s: count: %d, pass cnt: %d, fail cnt: %d, status: %X, param ver: %X %X %X %X\n",
__func__, ts->cali_report_try_cnt, ts->cali_report_pass_cnt,
ts->cali_report_fail_cnt, ts->cali_report_status,
ts->cali_report_param_ver[0], ts->cali_report_param_ver[1],
@@ -1103,6 +1143,244 @@ int sec_ts_read_calibration_report(struct sec_ts_data *ts)
return ts->cali_report_status;
}
+#define PTFLIB_ENCODED_ENABLED_OFFSET_LSB 0xA0
+#define PTFLIB_ENCODED_ENABLED_OFFSET_MSB 0x00
+#define PTFLIB_ENCODED_ENABLED_TRUE 0x01
+#define PTFLIB_ENCODED_ENABLED_FALSE 0x00
+static int sec_ts_ptflib_reinit(struct sec_ts_data *ts)
+{
+ u8 r_data[2] = {0x00, 0x00};
+ u8 w_data[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ int ret = 0;
+
+ /* Check whether encoded heatmap is inited in custom library. */
+ r_data[0] = PTFLIB_ENCODED_ENABLED_OFFSET_LSB;
+ r_data[1] = PTFLIB_ENCODED_ENABLED_OFFSET_MSB;
+ ret = sec_ts_read_from_customlib(ts, r_data, 2);
+ if (ret < 0) {
+ input_err(true, &ts->client->dev,
+ "%s: Read encoded heatmap's inited failed.\n",
+ __func__);
+ return -EIO;
+ }
+
+ if (r_data[1] != 0x01) {
+ input_err(true, &ts->client->dev,
+ "%s: Encoded heatmap was not initialized.\n",
+ __func__);
+ return -EIO;
+ }
+
+ /* Return if encoded heatmap is already enabled. */
+ if (r_data[0] == 0x01) {
+ input_info(true, &ts->client->dev,
+ "%s: Encoded heatmap is already enabled.\n",
+ __func__);
+ return 0;
+ }
+
+ /* Enable encoded heatmap. */
+ w_data[0] = PTFLIB_ENCODED_ENABLED_OFFSET_LSB;
+ w_data[1] = PTFLIB_ENCODED_ENABLED_OFFSET_MSB;
+ w_data[2] = PTFLIB_ENCODED_ENABLED_TRUE;
+ ret = sec_ts_write(ts, SEC_TS_CMD_CUSTOMLIB_WRITE_PARAM, w_data, 3);
+ if (ret < 0) {
+ input_err(true, &ts->client->dev,
+ "%s: ptlib - Writing encoded heatmap's enabled register failed.\n",
+ __func__);
+ return -EIO;
+ }
+
+ /* Check whether encoded heatmap is enabled in customlib. */
+ r_data[0] = PTFLIB_ENCODED_ENABLED_OFFSET_LSB;
+ r_data[1] = PTFLIB_ENCODED_ENABLED_OFFSET_MSB;
+ ret = sec_ts_read_from_customlib(ts, r_data, 2);
+ if (ret < 0) {
+ input_err(true, &ts->client->dev,
+ "%s: ptlib - Read encoded heatmap's enabled status failed.\n",
+ __func__);
+ return -EIO;
+ }
+
+ if (r_data[0] != PTFLIB_ENCODED_ENABLED_TRUE) {
+ input_err(true, &ts->client->dev,
+ "%s: ptlib - Enabling encoded heatmap failed.\n",
+ __func__);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+#define PTFLIB_GRIP_ENABLED_OFFSET_LSB 0x80
+#define PTFLIB_GRIP_ENABLED_OFFSET_MSB 0x00
+static int sec_ts_ptflib_grip_prescreen_enable(struct sec_ts_data *ts,
+ int grip_prescreen_mode) {
+ u8 r_data[2] = {0x00, 0x00};
+ u8 w_data[3] = {0x00, 0x00, 0x00};
+ int result;
+
+ input_info(true, &ts->client->dev, "%s: set mode %d.\n",
+ __func__, grip_prescreen_mode);
+
+ if (grip_prescreen_mode < GRIP_PRESCREEN_OFF ||
+ grip_prescreen_mode > GRIP_PRESCREEN_MODE_3) {
+ input_err(true, &ts->client->dev,
+ "%s: invalid grip_prescreen_mode value %d.\n",
+ __func__, grip_prescreen_mode);
+ return -EINVAL;
+ }
+
+ w_data[0] = PTFLIB_GRIP_ENABLED_OFFSET_LSB;
+ w_data[1] = PTFLIB_GRIP_ENABLED_OFFSET_MSB;
+ w_data[2] = grip_prescreen_mode;
+ result = ts->sec_ts_write(ts, SEC_TS_CMD_CUSTOMLIB_WRITE_PARAM,
+ w_data, 3);
+ if (result < 0) {
+ input_err(true, &ts->client->dev,
+ "%s: Write grip_prescreen_mode register failed.\n",
+ __func__);
+ return -EIO;
+ }
+
+ r_data[0] = PTFLIB_GRIP_ENABLED_OFFSET_LSB;
+ r_data[1] = PTFLIB_GRIP_ENABLED_OFFSET_MSB;
+ result = ts->sec_ts_read_customlib(ts, r_data, 2);
+ if (result < 0) {
+ input_err(true, &ts->client->dev,
+ "%s: Read grip_prescreen_mode register failed.\n",
+ __func__);
+ return -EIO;
+ }
+
+ if (r_data[0] != grip_prescreen_mode) {
+ input_err(true, &ts->client->dev,
+ "%s: Configure grip_prescreen_mode register failed %d.\n",
+ __func__, r_data[0]);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+#define PTFLIB_GRIP_PRESCREEN_TIMEOUT_OFFSET_LSB 0x9A
+#define PTFLIB_GRIP_PRESCREEN_TIMEOUT_OFFSET_MSB 0x00
+static int sec_ts_ptflib_grip_prescreen_timeout(struct sec_ts_data *ts,
+ int grip_prescreen_timeout) {
+ u8 r_data[2] = {0x00, 0x00};
+ u8 w_data[4] = {0x00, 0x00, 0x00, 0x00};
+ u16 timeout;
+ int result;
+
+ input_info(true, &ts->client->dev, "%s: set timeout %d.\n",
+ __func__, grip_prescreen_timeout);
+
+ if (grip_prescreen_timeout < GRIP_PRESCREEN_TIMEOUT_MIN ||
+ grip_prescreen_timeout > GRIP_PRESCREEN_TIMEOUT_MAX) {
+ input_err(true, &ts->client->dev,
+ "%s: invalid grip_prescreen_timeout value %d.\n",
+ __func__, grip_prescreen_timeout);
+ return -EINVAL;
+ }
+
+ w_data[0] = PTFLIB_GRIP_PRESCREEN_TIMEOUT_OFFSET_LSB;
+ w_data[1] = PTFLIB_GRIP_PRESCREEN_TIMEOUT_OFFSET_MSB;
+ w_data[2] = grip_prescreen_timeout & 0xFF;
+ w_data[3] = (grip_prescreen_timeout >> 8) & 0xFF;
+ result = ts->sec_ts_write(ts, SEC_TS_CMD_CUSTOMLIB_WRITE_PARAM,
+ w_data, 4);
+ if (result < 0) {
+ input_err(true, &ts->client->dev,
+ "%s: Write grip_prescreen_timeout register failed.\n",
+ __func__);
+ return -EIO;
+ }
+
+ r_data[0] = PTFLIB_GRIP_PRESCREEN_TIMEOUT_OFFSET_LSB;
+ r_data[1] = PTFLIB_GRIP_PRESCREEN_TIMEOUT_OFFSET_MSB;
+ result = ts->sec_ts_read_customlib(ts, r_data, 2);
+ if (result < 0) {
+ input_err(true, &ts->client->dev,
+ "%s: Read grip_prescreen_timeout register failed.\n",
+ __func__);
+ return -EIO;
+ }
+
+ timeout = le16_to_cpup((uint16_t *) r_data);
+ if (timeout != grip_prescreen_timeout) {
+ input_err(true, &ts->client->dev,
+ "%s: Configure grip_prescreen_timeout register failed %d.\n",
+ __func__, timeout);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+#define PTFLIB_GRIP_PRESCREEN_FRAMES_OFFSET_LSB 0x9C
+#define PTFLIB_GRIP_PRESCREEN_FRAMES_OFFSET_MSB 0x00
+static int sec_ts_ptflib_get_grip_prescreen_frames(struct sec_ts_data *ts) {
+ u8 r_data[4] = {0x00, 0x00, 0x00, 0x00};
+ int result;
+
+ r_data[0] = PTFLIB_GRIP_PRESCREEN_FRAMES_OFFSET_LSB;
+ r_data[1] = PTFLIB_GRIP_PRESCREEN_FRAMES_OFFSET_MSB;
+ result = ts->sec_ts_read_customlib(ts, r_data, sizeof(r_data));
+ if (result < 0) {
+ input_err(true, &ts->client->dev,
+ "%s: Read grip prescreen frames register failed.\n",
+ __func__);
+ return -EIO;
+ }
+
+ return le32_to_cpup((uint32_t *) r_data);
+}
+
+static int sec_ts_ptflib_decoder(struct sec_ts_data *ts, const u16 *in_array,
+ const int in_array_size, u16 *out_array,
+ const int out_array_max_size)
+{
+ const u16 ESCAPE_MASK = 0xF000;
+ const u16 ESCAPE_BIT = 0x8000;
+
+ int i;
+ int j;
+ int out_array_size = 0;
+ u16 prev_word = 0;
+ u16 repetition = 0;
+
+ for (i = 0; i < in_array_size; i++) {
+ u16 curr_word = in_array[i];
+ if ((curr_word & ESCAPE_MASK) == ESCAPE_BIT) {
+ repetition = (curr_word & ~ESCAPE_MASK) - 1;
+ if (out_array_size + repetition > out_array_max_size)
+ break;
+
+ for (j = 0; j < repetition; j++) {
+ *out_array++ = prev_word;
+ out_array_size++;
+ }
+ } else {
+ if (out_array_size >= out_array_max_size)
+ break;
+
+ *out_array++ = curr_word;
+ out_array_size++;
+ prev_word = curr_word;
+ }
+ }
+
+ if (i != in_array_size || out_array_size != out_array_max_size) {
+ input_info(true, &ts->client->dev,
+ "%s: %d (in=%d, out=%d, rep=%d, out_max=%d).\n",
+ __func__, i, in_array_size, out_array_size,
+ repetition, out_array_max_size);
+ return -1;
+ }
+
+ return out_array_size;
+}
+
static void sec_ts_reinit(struct sec_ts_data *ts)
{
u8 w_data[2] = {0x00, 0x00};
@@ -1240,13 +1518,13 @@ static void sec_ts_reinit(struct sec_ts_data *ts)
/* Update a state machine used to toggle control of the touch IC's motion
* filter.
*/
-static void update_motion_filter(struct sec_ts_data *ts)
+static void update_motion_filter(struct sec_ts_data *ts, unsigned long touch_id)
{
/* Motion filter timeout, in milliseconds */
const u32 mf_timeout_ms = 500;
u8 next_state;
/* Count the active touches */
- u8 touches = hweight32(ts->tid_touch_state);
+ u8 touches = hweight32(touch_id);
if (ts->use_default_mf)
return;
@@ -1305,11 +1583,20 @@ static void update_motion_filter(struct sec_ts_data *ts)
static bool read_heatmap_raw(struct v4l2_heatmap *v4l2)
{
struct sec_ts_data *ts = container_of(v4l2, struct sec_ts_data, v4l2);
- const struct sec_ts_plat_data *pdata = ts->plat_data;
+ struct sec_ts_plat_data *pdata = ts->plat_data;
int result;
int max_x = v4l2->format.width;
int max_y = v4l2->format.height;
+ if (ts->v4l2_mutual_strength_updated &&
+ ts->mutual_strength_heatmap.size_x == max_x &&
+ ts->mutual_strength_heatmap.size_y == max_y) {
+ memcpy(v4l2->frame, ts->mutual_strength_heatmap.data,
+ max_x * max_y * 2);
+ ts->v4l2_mutual_strength_updated = false;
+ return true;
+ }
+
if (ts->tsp_dump_lock == 1) {
input_info(true, &ts->client->dev,
"%s: drop this because raw data reading by others\n",
@@ -1328,30 +1615,38 @@ static bool read_heatmap_raw(struct v4l2_heatmap *v4l2)
u8 enable;
struct heatmap_report report = {0};
- result = sec_ts_read(ts,
- SEC_TS_CMD_HEATMAP_ENABLE, &enable, 1);
- if (result < 0) {
- input_err(true, &ts->client->dev,
- "%s: read reg %#x failed, returned %i\n",
- __func__, SEC_TS_CMD_HEATMAP_ENABLE, result);
- return false;
- }
-
- if (!enable) {
- enable = 1;
- result = sec_ts_write(ts,
+ if (!pdata->is_heatmap_enabled) {
+ result = sec_ts_read(ts,
SEC_TS_CMD_HEATMAP_ENABLE, &enable, 1);
- if (result < 0)
+ if (result < 0) {
input_err(true, &ts->client->dev,
- "%s: enable local heatmap failed, returned %i\n",
- __func__, result);
- /*
- * After local heatmap enabled, it takes `1/SCAN_RATE`
- * time to make data ready. But, we don't want to wait
- * here to cause overhead. Just drop this and wait for
- * next reading.
- */
- return false;
+ "%s: read reg %#x failed, returned %i\n",
+ __func__,
+ SEC_TS_CMD_HEATMAP_ENABLE, result);
+ return false;
+ }
+
+ if (!enable) {
+ enable = 1;
+ result = sec_ts_write(ts,
+ SEC_TS_CMD_HEATMAP_ENABLE, &enable, 1);
+ if (result < 0)
+ input_err(true, &ts->client->dev,
+ "%s: enable local heatmap failed, returned %i\n",
+ __func__, result);
+ else
+ pdata->is_heatmap_enabled = true;
+ /*
+ * After local heatmap enabled, it takes
+ * `1/SCAN_RATE` time to make data ready. But,
+ * we don't want to wait here to cause
+ * overhead. Just drop this and wait for next
+ * reading.
+ */
+ return false;
+ } else {
+ ts->plat_data->is_heatmap_enabled = true;
+ }
}
result = sec_ts_read(ts, SEC_TS_CMD_HEATMAP_READ,
@@ -1561,6 +1856,100 @@ static void sec_ts_handle_lib_status_event(struct sec_ts_data *ts,
}
#endif
+#ifdef SEC_TS_DEBUG_KFIFO_LEN
+inline void sec_ts_kfifo_push_coord(struct sec_ts_data *ts, u8 slot)
+{
+ if (slot < MAX_SUPPORT_TOUCH_COUNT) {
+ /*
+ * Use kfifo as circular buffer by skipping one element
+ * when fifo is full.
+ */
+ if (kfifo_is_full(&debug_fifo))
+ kfifo_skip(&debug_fifo);
+ kfifo_in(&debug_fifo, &ts->coord[slot], 1);
+ }
+}
+
+inline void sec_ts_kfifo_pop_all_coords(struct sec_ts_data *ts)
+{
+ /*
+ * Keep coords without pop-out to support different timing
+ * print-out by each caller.
+ */
+ kfifo_out_peek(&debug_fifo, last_coord, kfifo_size(&debug_fifo));
+}
+
+inline void sec_ts_debug_dump(struct sec_ts_data *ts)
+{
+ int i;
+ s64 delta;
+ s64 sec_longest_duration;
+ u32 ms_longest_duration;
+ s64 sec_delta_down;
+ u32 ms_delta_down;
+ s64 sec_delta_duration;
+ u32 ms_delta_duration;
+ s32 px_delta_x, px_delta_y;
+ ktime_t current_time = ktime_get();
+
+ sec_longest_duration = div_u64_rem(ts->longest_duration,
+ MSEC_PER_SEC, &ms_longest_duration);
+
+ sec_ts_kfifo_pop_all_coords(ts);
+ for (i = 0 ; i < ARRAY_SIZE(last_coord) ; i++) {
+ if (last_coord[i].action == SEC_TS_COORDINATE_ACTION_NONE) {
+ input_dbg(true, &ts->client->dev,
+ "dump: #%d: N/A!\n", last_coord[i].id);
+ continue;
+ }
+ sec_delta_down = -1;
+ ms_delta_down = 0;
+ /* calculate the delta of finger down from current time. */
+ delta = ktime_ms_delta(current_time, last_coord[i].ktime_pressed);
+ if (delta > 0)
+ sec_delta_down = div_u64_rem(delta, MSEC_PER_SEC, &ms_delta_down);
+
+ /* calculate the delta of finger duration between finger up and down. */
+ sec_delta_duration = -1;
+ ms_delta_duration = 0;
+ px_delta_x = 0;
+ px_delta_y = 0;
+ if (last_coord[i].action == SEC_TS_COORDINATE_ACTION_RELEASE) {
+ delta = ktime_ms_delta(last_coord[i].ktime_released,
+ last_coord[i].ktime_pressed);
+ if (delta > 0) {
+ sec_delta_duration = div_u64_rem(delta, MSEC_PER_SEC,
+ &ms_delta_duration);
+ px_delta_x = last_coord[i].x - last_coord[i].x_pressed;
+ px_delta_y = last_coord[i].y - last_coord[i].y_pressed;
+ }
+ }
+ input_info(true, &ts->client->dev,
+ "dump: #%d: %lld.%u(%lld.%u) D(%d, %d).\n",
+ last_coord[i].id,
+ sec_delta_down, ms_delta_down,
+ sec_delta_duration, ms_delta_duration,
+ px_delta_x, px_delta_y);
+ input_dbg(true, &ts->client->dev,
+ "dump-dbg: #%d: (%d, %d) (%d, %d).\n",
+ last_coord[i].id,
+ last_coord[i].x_pressed, last_coord[i].y_pressed,
+ last_coord[i].x, last_coord[i].y);
+ }
+ input_info(true, &ts->client->dev,
+ "dump: i/o %u, comm %u, reset %u, longest %lld.%u.\n",
+ ts->io_err_count, ts->comm_err_count, ts->hw_reset_count,
+ sec_longest_duration, ms_longest_duration);
+ input_info(true, &ts->client->dev,
+ "dump: cnt %u, active %u, wet %u, palm %u.\n",
+ ts->pressed_count, ts->touch_count, ts->wet_count, ts->palm_count);
+}
+#else
+#define sec_ts_kfifo_push_coord(ts, slot) do {} while (0)
+#define sec_ts_kfifo_pop_all_coords(ts) do {} while (0)
+#define sec_ts_debug_dump(ts) do {} while (0)
+#endif /* #ifdef SEC_TS_DEBUG_KFIFO_LEN */
+
static void sec_ts_handle_coord_event(struct sec_ts_data *ts,
struct sec_ts_event_coordinate *p_event_coord)
{
@@ -1585,12 +1974,14 @@ static void sec_ts_handle_coord_event(struct sec_ts_data *ts,
SEC_TS_PRESSURE_MAX;
ts->coord[t_id].ttype = p_event_coord->ttype_3_2 << 2 |
p_event_coord->ttype_1_0 << 0;
- ts->coord[t_id].major = p_event_coord->major;
- ts->coord[t_id].minor = p_event_coord->minor;
+ ts->coord[t_id].major = p_event_coord->major *
+ ts->plat_data->mm2px;
+ ts->coord[t_id].minor = p_event_coord->minor *
+ ts->plat_data->mm2px;
if (!ts->coord[t_id].palm &&
(ts->coord[t_id].ttype == SEC_TS_TOUCHTYPE_PALM))
- ts->coord[t_id].palm_count++;
+ ts->palm_count++;
ts->coord[t_id].palm =
(ts->coord[t_id].ttype == SEC_TS_TOUCHTYPE_PALM);
@@ -1609,6 +2000,7 @@ static void sec_ts_handle_coord_event(struct sec_ts_data *ts,
ts->offload.coords[t_id].major = ts->coord[t_id].major;
ts->offload.coords[t_id].minor = ts->coord[t_id].minor;
ts->offload.coords[t_id].pressure = ts->coord[t_id].z;
+ ts->offload.coords[t_id].rotation = 0;
#endif
if ((ts->coord[t_id].ttype ==
@@ -1622,17 +2014,14 @@ static void sec_ts_handle_coord_event(struct sec_ts_data *ts,
(ts->coord[t_id].ttype ==
SEC_TS_TOUCHTYPE_GLOVE)) {
- if (ts->coord[t_id].action ==
- SEC_TS_COORDINATE_ACTION_RELEASE) {
+ if (ts->coord[t_id].action == SEC_TS_COORDINATE_ACTION_RELEASE) {
+ s64 ms_delta;
- ktime_get_real_ts64(&ts->time_released[t_id]);
-
- if (ts->time_longest <
- (ts->time_released[t_id].tv_sec -
- ts->time_pressed[t_id].tv_sec))
- ts->time_longest =
- (ts->time_released[t_id].tv_sec
- - ts->time_pressed[t_id].tv_sec);
+ ts->coord[t_id].ktime_released = ktime_get();
+ ms_delta = ktime_ms_delta(ts->coord[t_id].ktime_released,
+ ts->coord[t_id].ktime_pressed);
+ if (ts->longest_duration < ms_delta)
+ ts->longest_duration = ms_delta;
if (ts->touch_count > 0)
ts->touch_count--;
@@ -1668,8 +2057,8 @@ static void sec_ts_handle_coord_event(struct sec_ts_data *ts,
#endif
} else if (ts->coord[t_id].action ==
SEC_TS_COORDINATE_ACTION_PRESS) {
- ktime_get_real_ts64(&ts->time_pressed[t_id]);
-
+ ts->coord[t_id].ktime_pressed = ktime_get();
+ ts->pressed_count++;
ts->touch_count++;
if ((ts->touch_count > 4) &&
(ts->check_multi == 0)) {
@@ -1678,6 +2067,8 @@ static void sec_ts_handle_coord_event(struct sec_ts_data *ts,
}
ts->all_finger_count++;
+ ts->coord[t_id].x_pressed = ts->coord[t_id].x;
+ ts->coord[t_id].y_pressed = ts->coord[t_id].y;
ts->max_z_value = max_t(unsigned int,
ts->coord[t_id].z,
ts->max_z_value);
@@ -1846,9 +2237,10 @@ static void sec_ts_handle_coord_event(struct sec_ts_data *ts,
__func__, t_id);
if (t_id < MAX_SUPPORT_TOUCH_COUNT + MAX_SUPPORT_HOVER_COUNT) {
+
if (ts->coord[t_id].action == SEC_TS_COORDINATE_ACTION_PRESS) {
input_dbg(false, &ts->client->dev,
- "%s[P] tID:%d x:%d y:%d z:%d major:%d minor:%d tc:%d type:%X\n",
+ "%s[P] tID: %d x: %d y: %d z: %d major: %d minor: %d tc: %u type: %X\n",
ts->dex_name,
t_id, ts->coord[t_id].x,
ts->coord[t_id].y, ts->coord[t_id].z,
@@ -1859,8 +2251,9 @@ static void sec_ts_handle_coord_event(struct sec_ts_data *ts,
} else if (ts->coord[t_id].action ==
SEC_TS_COORDINATE_ACTION_RELEASE) {
+ sec_ts_kfifo_push_coord(ts, t_id);
input_dbg(false, &ts->client->dev,
- "%s[R] tID:%d mc:%d tc:%d lx:%d ly:%d v:%02X%02X cal:%02X(%02X) id(%d,%d) p:%d\n",
+ "%s[R] tID: %d mc: %d tc: %u lx: %d ly: %d v: %02X%02X cal: %02X(%02X) id(%d,%d)\n",
ts->dex_name,
t_id, ts->coord[t_id].mcount,
ts->touch_count,
@@ -1868,11 +2261,9 @@ static void sec_ts_handle_coord_event(struct sec_ts_data *ts,
ts->plat_data->img_version_of_ic[2],
ts->plat_data->img_version_of_ic[3],
ts->cal_status, ts->nv, ts->tspid_val,
- ts->tspicid_val,
- ts->coord[t_id].palm_count);
+ ts->tspicid_val);
ts->coord[t_id].mcount = 0;
- ts->coord[t_id].palm_count = 0;
}
}
}
@@ -1958,10 +2349,153 @@ static void sec_ts_populate_coordinate_channel(struct sec_ts_data *ts,
dc->coords[j].major = ts->offload.coords[j].major;
dc->coords[j].minor = ts->offload.coords[j].minor;
dc->coords[j].pressure = ts->offload.coords[j].pressure;
+ dc->coords[j].rotation = ts->offload.coords[j].rotation;
dc->coords[j].status = ts->offload.coords[j].status;
}
}
+static void sec_ts_update_v4l2_mutual_strength(struct sec_ts_data *ts,
+ uint32_t size_x,
+ uint32_t size_y,
+ int16_t *heatmap)
+{
+ if (!ts->mutual_strength_heatmap.data) {
+ ts->mutual_strength_heatmap.data = devm_kmalloc(
+ &ts->client->dev, size_x * size_y * 2, GFP_KERNEL);
+ if (!ts->mutual_strength_heatmap.data) {
+ input_err(true, &ts->client->dev,
+ "%s: kmalloc for mutual_strength_heatmap (%d) failed.\n",
+ __func__, size_x * size_y * 2);
+ } else {
+ ts->mutual_strength_heatmap.size_x = size_x;
+ ts->mutual_strength_heatmap.size_y = size_y;
+ input_info(true, &ts->client->dev,
+ "%s: kmalloc for mutual_strength_heatmap (%d).\n",
+ __func__, size_x * size_y * 2);
+ }
+ }
+
+ if (ts->mutual_strength_heatmap.data) {
+ if (ts->mutual_strength_heatmap.size_x == size_x &&
+ ts->mutual_strength_heatmap.size_y == size_y) {
+ memcpy(ts->mutual_strength_heatmap.data,
+ heatmap, size_x * size_y * 2);
+ ts->mutual_strength_heatmap.timestamp =
+ ts->timestamp;
+ ts->v4l2_mutual_strength_updated = true;
+ } else {
+ input_info(true, &ts->client->dev,
+ "%s: unmatched heatmap size (%d,%d) (%d,%d).\n",
+ __func__, size_x, size_y,
+ ts->mutual_strength_heatmap.size_x,
+ ts->mutual_strength_heatmap.size_y);
+ }
+ }
+}
+
+#define PTFLIB_ENCODED_COUNTER_OFFSET 0x00A8
+#define PTFLIB_ENCODED_COUNTER_READ_SIZE 6
+#define PTFLIB_ENCODED_DATA_READ_SIZE 338
+static int sec_ts_populate_encoded_channel(struct sec_ts_data *ts,
+ struct touch_offload_frame *frame,
+ int channel)
+{
+ u32 heatmap_array_len = 0;
+ u32 decoded_size = 0;
+ u32 encoded_counter = 0;
+ u16 read_src_offset = 0;
+ int read_src_size = 0;
+ u8 *r_data;
+ u16 encoded_data_size = 0;
+ u16 first_word = 0;
+ int i;
+ int x;
+ int y;
+ int ret = 0;
+ ktime_t timestamp_read_start;
+ ktime_t timestamp_read_end;
+ struct TouchOffloadData2d *mutual_strength =
+ (struct TouchOffloadData2d *)frame->channel_data[channel];
+
+ mutual_strength->tx_size = ts->tx_count;
+ mutual_strength->rx_size = ts->rx_count;
+ mutual_strength->header.channel_type = frame->channel_type[channel];
+ mutual_strength->header.channel_size =
+ TOUCH_OFFLOAD_FRAME_SIZE_2D(mutual_strength->rx_size,
+ mutual_strength->tx_size);
+ heatmap_array_len = ts->tx_count * ts->rx_count;
+
+ if (!ts->encoded_buff) {
+ ts->encoded_buff = kmalloc(
+ heatmap_array_len * 2 + PTFLIB_ENCODED_COUNTER_READ_SIZE,
+ GFP_KERNEL);
+ if (!ts->encoded_buff) {
+ input_err(true, &ts->client->dev,
+ "%s: kmalloc for encoded_buff failed.\n",
+ __func__);
+ return -ENOMEM;
+ }
+ }
+
+ /* Read encoded heatmap from customlib. */
+ read_src_offset = PTFLIB_ENCODED_COUNTER_OFFSET;
+ read_src_size = PTFLIB_ENCODED_COUNTER_READ_SIZE +
+ PTFLIB_ENCODED_DATA_READ_SIZE;
+ r_data = (u8 *) ts->encoded_buff;
+ r_data[0] = read_src_offset & 0xFF;
+ r_data[1] = (read_src_offset >> 8) & 0xFF;
+ timestamp_read_start = ktime_get();
+ ret = sec_ts_read_from_customlib(ts, r_data, read_src_size);
+ if (ret < 0) {
+ input_err(true, &ts->client->dev,
+ "%s: Read customlib failed, offset(0x%04X)) size(%d)\n",
+ __func__, read_src_offset, read_src_size);
+ return -EIO;
+ }
+ timestamp_read_end = ktime_get();
+
+ encoded_counter = le32_to_cpup((uint32_t *) r_data);
+ encoded_data_size = le16_to_cpup((uint16_t *) &r_data[4]);
+ first_word = le16_to_cpup((uint16_t *) &r_data[6]);
+
+ if (encoded_counter == 0 || encoded_data_size == 0 ||
+ first_word == 0x8FFF ||
+ encoded_data_size > PTFLIB_ENCODED_DATA_READ_SIZE) {
+ decoded_size = 0;
+ } else {
+ decoded_size = sec_ts_ptflib_decoder(ts, (u16 *) (r_data + 6),
+ encoded_data_size / 2,
+ (u16 *) ts->heatmap_buff,
+ heatmap_array_len);
+ }
+
+ ts->plat_data->encoded_frame_counter++;
+ if (decoded_size != heatmap_array_len) {
+ ts->plat_data->encoded_skip_counter++;
+ input_info(true, &ts->client->dev,
+ "%s: %d (%d,0x%04X,0x%04X,%d) ts(%lld,%lld)\n",
+ __func__, encoded_counter,
+ encoded_data_size & 0x0FFF, encoded_data_size,
+ first_word, decoded_size,
+ ktime_us_delta(timestamp_read_start, ts->timestamp),
+ ktime_us_delta(timestamp_read_end,
+ timestamp_read_start));
+ return -EIO;
+ }
+
+ i = 0;
+ for (y = mutual_strength->rx_size - 1; y >= 0; y--)
+ for (x = mutual_strength->tx_size - 1; x >= 0; x--)
+ ((uint16_t *) mutual_strength->data)[i++] =
+ ts->heatmap_buff[x * mutual_strength->rx_size + y];
+
+ sec_ts_update_v4l2_mutual_strength(ts, mutual_strength->tx_size,
+ mutual_strength->rx_size,
+ (int16_t *) mutual_strength->data);
+
+ return 0;
+}
+
static void sec_ts_populate_mutual_channel(struct sec_ts_data *ts,
struct touch_offload_frame *frame,
int channel)
@@ -2063,6 +2597,12 @@ static void sec_ts_populate_mutual_channel(struct sec_ts_data *ts,
be16_to_cpu(heatmap_value);
}
}
+
+ if (target_data_type == TYPE_SIGNAL_DATA) {
+ sec_ts_update_v4l2_mutual_strength(ts,
+ mutual_strength->tx_size, mutual_strength->rx_size,
+ (int16_t *) mutual_strength->data);
+ }
}
static void sec_ts_populate_self_channel(struct sec_ts_data *ts,
@@ -2171,11 +2711,30 @@ static void sec_ts_populate_self_channel(struct sec_ts_data *ts,
}
}
+static void sec_ts_populate_driver_status_channel(struct sec_ts_data *ts,
+ struct touch_offload_frame *frame,
+ int channel)
+{
+ 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 = 1;
+ ds->screen_state = (ts->power_status == SEC_TS_STATE_POWER_ON) ? 1 : 0;
+
+ ds->display_refresh_rate = ts->display_refresh_rate;
+ ds->contents.display_refresh_rate = 1;
+}
+
static void sec_ts_populate_frame(struct sec_ts_data *ts,
struct touch_offload_frame *frame)
{
static u64 index;
int i;
+ int retval = -1;
+ const struct sec_ts_plat_data *pdata = ts->plat_data;
frame->header.index = index++;
frame->header.timestamp = ts->timestamp;
@@ -2187,38 +2746,90 @@ static void sec_ts_populate_frame(struct sec_ts_data *ts,
/* Populate all channels */
for (i = 0; i < frame->num_channels; i++) {
- if (frame->channel_type[i] == TOUCH_DATA_TYPE_COORD)
+ u8 channel_type = frame->channel_type[i];
+
+ if (channel_type == TOUCH_DATA_TYPE_COORD) {
sec_ts_populate_coordinate_channel(ts, frame, i);
- else if ((frame->channel_type[i] & TOUCH_SCAN_TYPE_MUTUAL) != 0)
- sec_ts_populate_mutual_channel(ts, frame, i);
- else if ((frame->channel_type[i] & TOUCH_SCAN_TYPE_SELF) != 0)
+ } else if ((channel_type & TOUCH_SCAN_TYPE_MUTUAL) != 0) {
+ if ((pdata->encoded_enable == ENCODED_ENABLE_ON) &&
+ ((channel_type & ~TOUCH_SCAN_TYPE_MUTUAL) ==
+ TOUCH_DATA_TYPE_STRENGTH))
+ retval = sec_ts_populate_encoded_channel(
+ ts, frame, i);
+ if (retval < 0)
+ sec_ts_populate_mutual_channel(ts, frame, i);
+ } else if ((channel_type & TOUCH_SCAN_TYPE_SELF) != 0) {
sec_ts_populate_self_channel(ts, frame, i);
+ } else if ((frame->channel_type[i] ==
+ CONTEXT_CHANNEL_TYPE_DRIVER_STATUS) != 0)
+ sec_ts_populate_driver_status_channel(ts, frame, i);
+ else if ((frame->channel_type[i] ==
+ CONTEXT_CHANNEL_TYPE_STYLUS_STATUS) != 0) {
+ /* Stylus context is not required by this driver */
+ input_err(true, &ts->client->dev,
+ "%s: Driver does not support stylus status",
+ __func__);
+ }
+ }
+}
+
+void sec_ts_enable_ptflib(struct sec_ts_data *ts, bool enable)
+{
+ struct sec_ts_plat_data *pdata = ts->plat_data;
+
+ input_info(true, &ts->client->dev,
+ "%s: enable %d.\n", __func__, enable);
+
+ if (enable) {
+ sec_ts_ptflib_reinit(ts);
+ if (pdata->grip_prescreen_mode == GRIP_PRESCREEN_MODE_2) {
+ sec_ts_ptflib_grip_prescreen_timeout(ts,
+ pdata->grip_prescreen_timeout);
+ }
+ sec_ts_ptflib_grip_prescreen_enable(ts,
+ pdata->grip_prescreen_mode);
+ } else {
+ sec_ts_ptflib_grip_prescreen_enable(ts, GRIP_PRESCREEN_OFF);
}
}
-int sec_ts_enable_grip(struct sec_ts_data *ts, bool enable)
+int sec_ts_enable_fw_grip(struct sec_ts_data *ts, bool enable)
{
- u8 value = enable ? 1 : 0;
+ struct sec_ts_plat_data *pdata = ts->plat_data;
+ u8 value;
int ret;
int final_result = 0;
+ input_info(true, &ts->client->dev,
+ "%s: enable %d.\n", __func__, enable);
+
/* Set grip */
+ value = enable ? 0x1F : 0;
ret = ts->sec_ts_write(ts, SEC_TS_CMD_SET_GRIP_DETEC, &value, 1);
if (ret < 0) {
input_err(true, &ts->client->dev,
"%s: SEC_TS_CMD_SET_GRIP_DETEC failed with ret=%d\n",
__func__, ret);
final_result = ret;
- }
-
- /* Set deadzone */
- value = enable ? 1 : 0;
- ret = ts->sec_ts_write(ts, SEC_TS_CMD_EDGE_DEADZONE, &value, 1);
- if (ret < 0) {
- input_err(true, &ts->client->dev,
- "%s: SEC_TS_CMD_EDGE_DEADZONE failed with ret=%d\n",
- __func__, ret);
- final_result = ret;
+ } else {
+ /* Configure grip */
+ if (enable) {
+ u8 mm = 10;
+ u8 px_lo = (mm * pdata->mm2px) & 0xFF;
+ u8 px_hi = ((mm * pdata->mm2px) >> 8) & 0xFF;
+ u8 long_press_zone[10] = {0x02, 0x00, /* long press reject zone type */
+ px_hi, px_lo, /* left edge */
+ 0x00, 0x00, /* top edge */
+ px_hi, px_lo, /* right edge */
+ 0x00, 0x00}; /* bottom edge */
+ ret = ts->sec_ts_write(ts, SEC_TS_CMD_LONGPRESS_DROP_AREA,
+ long_press_zone, sizeof(long_press_zone));
+ if (ret < 0) {
+ input_err(true, &ts->client->dev,
+ "%s: SEC_TS_CMD_LONGPRESS_DROP_AREA failed with ret=%d\n",
+ __func__, ret);
+ }
+ }
}
return final_result;
@@ -2228,18 +2839,43 @@ static void sec_ts_offload_set_running(struct sec_ts_data *ts, bool running)
{
if (ts->offload.offload_running != running) {
ts->offload.offload_running = running;
- if (running) {
- pr_info("%s: disabling FW grip.\n", __func__);
- sec_ts_enable_grip(ts, false);
+ if (running && ts->offload.config.filter_grip) {
+ sec_ts_enable_fw_grip(ts, false);
+ sec_ts_enable_ptflib(ts, true);
} else {
- pr_info("%s: enabling FW grip.\n", __func__);
- sec_ts_enable_grip(ts, true);
+ sec_ts_enable_fw_grip(ts, true);
+ sec_ts_enable_ptflib(ts, false);
}
}
}
#endif /* CONFIG_TOUCHSCREEN_OFFLOAD */
+static void sec_ts_handle_fod_event(struct sec_ts_data *ts,
+ struct sec_ts_event_status *p_event_status)
+{
+ struct sec_ts_fod_event *p_fod =
+ (struct sec_ts_fod_event *)p_event_status;
+ int x = p_fod->x_b11_b8 << 8 | p_fod->x_b7_b0;
+ int y = p_fod->y_b11_b8 << 8 | p_fod->y_b7_b0;
+
+ if (test_bit(0, &ts->tid_touch_state)) {
+ input_info(true, &ts->client->dev,
+ "%s: slot 0 is in use!", __func__);
+ return;
+ }
+
+ if (!x || !y) {
+ input_info(true, &ts->client->dev,
+ "%s: one of coords is ZERO(%d, %d)!",
+ __func__, x, y);
+ x = ts->plat_data->fod_x;
+ y = ts->plat_data->fod_y;
+ }
+
+ input_info(true, &ts->client->dev,
+ "STATUS: FoD: %s, X,Y: %d, %d\n", p_fod->status ? "ON" : "OFF", x, y);
+}
static void sec_ts_read_vendor_event(struct sec_ts_data *ts,
struct sec_ts_event_status *p_event_status)
@@ -2272,39 +2908,55 @@ static void sec_ts_read_vendor_event(struct sec_ts_data *ts,
break;
case SEC_TS_EVENT_STATUS_ID_REPORT_RATE:
- if (ts->debug)
+ ts->report_rate = status_data_1;
+ if (ts->debug_status)
input_info(true,
&ts->client->dev,
"STATUS: rate %d -> %d\n",
status_data_2, status_data_1);
break;
+ case SEC_TS_EVENT_STATUS_ID_VSYNC:
+ ts->vsync = status_data_1;
+ if (ts->debug_status)
+ input_info(true,
+ &ts->client->dev,
+ "STATUS: vsync %d -> %d\n",
+ status_data_2, status_data_1);
+ break;
+
case SEC_TS_EVENT_STATUS_ID_WLC:
input_info(true,
&ts->client->dev,
- "STATUS: wlc mode change to %x\n",
+ "STATUS: WLC: %#x\n",
status_data_1);
break;
case SEC_TS_EVENT_STATUS_ID_NOISE:
input_info(true,
&ts->client->dev,
- "STATUS: noise mode change to %x\n",
+ "STATUS: noise: %#x\n",
status_data_1);
break;
case SEC_TS_EVENT_STATUS_ID_GRIP:
- input_info(true,
- &ts->client->dev,
- "STATUS: detect grip %s!\n",
- (status_data_1) ?
- "enter" : "leave");
+ if (ts->debug_status)
+ input_info(true,
+ &ts->client->dev,
+ "STATUS: grip: %d.\n",
+ status_data_1);
break;
case SEC_TS_EVENT_STATUS_ID_PALM:
- input_info(true,
- &ts->client->dev,
- "STATUS: detect palm!\n");
+ input_info(true, &ts->client->dev,
+ "STATUS: palm: %d.\n",
+ status_data_1);
+ if (status_data_1)
+ ts->palm_count++;
+ break;
+
+ case SEC_TS_EVENT_STATUS_ID_FOD:
+ sec_ts_handle_fod_event(ts, p_event_status);
break;
default:
@@ -2381,7 +3033,7 @@ static void sec_ts_read_event(struct sec_ts_data *ts)
return;
}
- if (ts->debug == 0x01)
+ if (ts->debug_events)
input_info(true, &ts->client->dev,
"ONE: %02X %02X %02X %02X %02X %02X %02X %02X\n",
read_event_buff[0][0], read_event_buff[0][1],
@@ -2430,7 +3082,7 @@ static void sec_ts_read_event(struct sec_ts_data *ts)
event_buff = read_event_buff[curr_pos];
event_id = event_buff[0] & 0x3;
- if (ts->debug == 0x01)
+ if (ts->debug_events && curr_pos > 0)
input_info(true, &ts->client->dev,
"ALL: %02X %02X %02X %02X %02X %02X %02X %02X\n",
event_buff[0], event_buff[1], event_buff[2],
@@ -2455,7 +3107,7 @@ static void sec_ts_read_event(struct sec_ts_data *ts)
switch (status_data_1) {
case 0x20:
/* watchdog reset !? */
- sec_ts_unlocked_release_all_finger(ts);
+ sec_ts_locked_release_all_finger(ts);
ret = sec_ts_write(ts,
SEC_TS_CMD_SENSE_ON, NULL, 0);
if (ret < 0)
@@ -2467,16 +3119,16 @@ static void sec_ts_read_event(struct sec_ts_data *ts)
break;
case 0x40:
input_info(true, &ts->client->dev,
- "%s: sw_reset done\n",
+ "%s: sw_reset ack.\n",
__func__);
- sec_ts_unlocked_release_all_finger(ts);
+ sec_ts_locked_release_all_finger(ts);
complete_all(&ts->boot_completed);
break;
case 0x10:
input_info(true, &ts->client->dev,
- "%s: hw_reset done\n",
+ "%s: hw_reset ack.\n",
__func__);
- sec_ts_unlocked_release_all_finger(ts);
+ sec_ts_locked_release_all_finger(ts);
complete_all(&ts->boot_completed);
break;
default:
@@ -2492,7 +3144,7 @@ static void sec_ts_read_event(struct sec_ts_data *ts)
input_err(true, &ts->client->dev,
"%s: IC Event Queue is full\n",
__func__);
- sec_ts_unlocked_release_all_finger(ts);
+ sec_ts_locked_release_all_finger(ts);
}
if ((p_event_status->stype ==
@@ -2521,21 +3173,27 @@ static void sec_ts_read_event(struct sec_ts_data *ts)
}
#ifdef SEC_TS_SUPPORT_CUSTOMLIB
+ mutex_lock(&ts->eventlock);
sec_ts_handle_lib_status_event(ts, p_event_status);
+ mutex_unlock(&ts->eventlock);
#endif
break;
case SEC_TS_COORDINATE_EVENT:
processed_pointer_event = true;
+ mutex_lock(&ts->eventlock);
sec_ts_handle_coord_event(ts,
(struct sec_ts_event_coordinate *)event_buff);
+ mutex_unlock(&ts->eventlock);
break;
case SEC_TS_GESTURE_EVENT:
p_gesture_status =
(struct sec_ts_gesture_status *)event_buff;
#ifdef SEC_TS_SUPPORT_CUSTOMLIB
+ mutex_lock(&ts->eventlock);
sec_ts_handle_gesture_event(ts, p_gesture_status);
+ mutex_unlock(&ts->eventlock);
#endif
break;
@@ -2554,8 +3212,10 @@ static void sec_ts_read_event(struct sec_ts_data *ts)
#if IS_ENABLED(CONFIG_TOUCHSCREEN_OFFLOAD)
if (!ts->offload.offload_running) {
#endif
-
+ mutex_lock(&ts->eventlock);
+ input_set_timestamp(ts->input_dev, ts->timestamp);
input_sync(ts->input_dev);
+ mutex_unlock(&ts->eventlock);
#if IS_ENABLED(CONFIG_TOUCHSCREEN_OFFLOAD)
}
@@ -2587,7 +3247,9 @@ static void sec_ts_read_event(struct sec_ts_data *ts)
*/
#if IS_ENABLED(CONFIG_TOUCHSCREEN_HEATMAP)
if (processed_pointer_event) {
- heatmap_read(&ts->v4l2, ktime_to_ns(ts->timestamp));
+ if (ts->heatmap_init_done && !ts->offload.offload_running) {
+ heatmap_read(&ts->v4l2, ktime_to_ns(ts->timestamp));
+ }
/* palm */
if (last_tid_palm_state == 0 &&
@@ -2633,6 +3295,10 @@ static void sec_ts_read_event(struct sec_ts_data *ts)
"COORD: all fingers released with palm(s)/grip(s) leaved once\n");
}
}
+
+ /* Disable the firmware motion filter during single touch */
+ if (!ts->offload.offload_running)
+ update_motion_filter(ts, ts->tid_touch_state);
#endif
}
@@ -2641,9 +3307,6 @@ static irqreturn_t sec_ts_isr(int irq, void *handle)
struct sec_ts_data *ts = (struct sec_ts_data *)handle;
ts->timestamp = ktime_get();
-#if !IS_ENABLED(CONFIG_TOUCHSCREEN_OFFLOAD)
- /* input_set_timestamp(ts->input_dev, ts->timestamp); */
-#endif
return IRQ_WAKE_THREAD;
}
@@ -2664,17 +3327,8 @@ static irqreturn_t sec_ts_irq_thread(int irq, void *ptr)
cpu_latency_qos_update_request(&ts->pm_qos_req, 100);
pm_wakeup_event(&ts->client->dev, MSEC_PER_SEC);
- mutex_lock(&ts->eventlock);
-
sec_ts_read_event(ts);
- mutex_unlock(&ts->eventlock);
-
-#if IS_ENABLED(CONFIG_TOUCHSCREEN_HEATMAP)
- /* Disable the firmware motion filter during single touch */
- update_motion_filter(ts);
-#endif
-
cpu_latency_qos_update_request(&ts->pm_qos_req, PM_QOS_DEFAULT_VALUE);
sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_IRQ, false);
@@ -2688,14 +3342,18 @@ static void sec_ts_offload_report(void *handle,
{
struct sec_ts_data *ts = (struct sec_ts_data *)handle;
bool touch_down = 0;
+ unsigned long touch_id = 0;
int i;
+ mutex_lock(&ts->eventlock);
+
input_set_timestamp(ts->input_dev, report->timestamp);
for (i = 0; i < MAX_COORDS; i++) {
if (report->coords[i].status == COORD_STATUS_FINGER) {
input_mt_slot(ts->input_dev, i);
touch_down = 1;
+ __set_bit(i, &touch_id);
input_report_key(ts->input_dev, BTN_TOUCH,
touch_down);
input_mt_report_slot_state(ts->input_dev,
@@ -2712,6 +3370,8 @@ static void sec_ts_offload_report(void *handle,
input_report_abs(ts->input_dev,
ABS_MT_PRESSURE,
report->coords[i].pressure);
+ input_report_abs(ts->input_dev, ABS_MT_ORIENTATION,
+ report->coords[i].rotation);
} else {
input_mt_slot(ts->input_dev, i);
input_report_abs(ts->input_dev, ABS_MT_PRESSURE, 0);
@@ -2719,12 +3379,21 @@ static void sec_ts_offload_report(void *handle,
MT_TOOL_FINGER, 0);
input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID,
-1);
+ input_report_abs(ts->input_dev, ABS_MT_ORIENTATION, 0);
}
}
input_report_key(ts->input_dev, BTN_TOUCH, touch_down);
input_sync(ts->input_dev);
+
+ mutex_unlock(&ts->eventlock);
+
+ if (touch_down)
+ heatmap_read(&ts->v4l2, ktime_to_ns(report->timestamp));
+
+ /* Disable the firmware motion filter during single touch */
+ update_motion_filter(ts, touch_id);
}
#endif /* CONFIG_TOUCHSCREEN_OFFLOAD */
@@ -2749,7 +3418,7 @@ int sec_ts_glove_mode_enables(struct sec_ts_data *ts, int mode)
if (ts->power_status == SEC_TS_STATE_POWER_OFF) {
input_err(true, &ts->client->dev,
- "%s: pwr off, glove:%d, status:%x\n", __func__,
+ "%s: pwr off, glove: %d, status: %x\n", __func__,
mode, ts->touch_functions);
goto glove_enable_err;
}
@@ -2763,7 +3432,7 @@ int sec_ts_glove_mode_enables(struct sec_ts_data *ts, int mode)
}
input_info(true, &ts->client->dev,
- "%s: glove:%d, status:%x\n", __func__,
+ "%s: glove: %d, status: %x\n", __func__,
mode, ts->touch_functions);
return 0;
@@ -2815,7 +3484,7 @@ int sec_ts_set_cover_type(struct sec_ts_data *ts, bool enable)
if (ts->power_status == SEC_TS_STATE_POWER_OFF) {
input_err(true, &ts->client->dev,
- "%s: pwr off, close:%d, status:%x\n", __func__,
+ "%s: pwr off, close: %d, status: %x\n", __func__,
enable, ts->touch_functions);
goto cover_enable_err;
}
@@ -2840,7 +3509,7 @@ int sec_ts_set_cover_type(struct sec_ts_data *ts, bool enable)
}
input_info(true, &ts->client->dev,
- "%s: close:%d, status:%x\n", __func__,
+ "%s: close: %d, status: %x\n", __func__,
enable, ts->touch_functions);
return 0;
@@ -2857,7 +3526,7 @@ void sec_ts_set_grip_type(struct sec_ts_data *ts, u8 set_type)
u8 mode = G_NONE;
input_info(true, &ts->client->dev,
- "%s: re-init grip(%d), edh:%d, edg:%d, lan:%d\n", __func__,
+ "%s: re-init grip(%d), edh: %d, edg: %d, lan: %d\n", __func__,
set_type, ts->grip_edgehandler_direction, ts->grip_edge_range,
ts->grip_landscape_mode);
@@ -3017,6 +3686,7 @@ static int sec_ts_parse_dt(struct spi_device *client)
struct sec_ts_plat_data *pdata = dev->platform_data;
struct device_node *np = dev->of_node;
u32 coords[2];
+ u8 offload_id[4];
int ret = 0;
int count = 0;
u32 ic_match_value;
@@ -3069,10 +3739,10 @@ static int sec_ts_parse_dt(struct spi_device *client)
"%s: Failed to get tsp-icid gpio\n", __func__);
}
- pdata->tsp_vsync = of_get_named_gpio(np, "sec,tsp_vsync_gpio", 0);
- if (gpio_is_valid(pdata->tsp_vsync))
+ pdata->vsync_gpio = of_get_named_gpio(np, "sec,tsp_vsync_gpio", 0);
+ if (gpio_is_valid(pdata->vsync_gpio))
input_info(true, &client->dev, "%s: vsync %s\n", __func__,
- gpio_get_value(pdata->tsp_vsync) ?
+ gpio_get_value(pdata->vsync_gpio) ?
"disable" : "enable");
pdata->irq_gpio = of_get_named_gpio(np, "sec,irq_gpio", 0);
@@ -3122,12 +3792,24 @@ static int sec_ts_parse_dt(struct spi_device *client)
pdata->max_x = coords[0] - 1;
pdata->max_y = coords[1] - 1;
+ if (of_property_read_u32_array(np, "sec,fod_coords", coords, 2)) {
+ input_info(true, &client->dev,
+ "%s: sec,fod_coords not found!\n", __func__);
+ coords[0] = 0;
+ coords[1] = 0;
+ }
+ pdata->fod_x = coords[0];
+ pdata->fod_y = coords[1];
+
#ifdef PAT_CONTROL
if (of_property_read_u32(np, "sec,pat_function",
&pdata->pat_function) < 0) {
pdata->pat_function = 0;
input_err(true, dev,
"%s: Failed to get pat_function property\n", __func__);
+ } else {
+ input_info(true, dev,
+ "%s: pat_function: %#x\n", __func__, pdata->pat_function);
}
if (of_property_read_u32(np, "sec,afe_base", &pdata->afe_base) < 0) {
@@ -3167,7 +3849,7 @@ static int sec_ts_parse_dt(struct spi_device *client)
return -EINVAL;
}
} else {
- input_err(true, dev, "%s: Failed to get switch_gpio\n",
+ input_info(true, dev, "%s: unavailable switch_gpio!\n",
__func__);
}
@@ -3262,6 +3944,16 @@ static int sec_ts_parse_dt(struct spi_device *client)
&pdata->mis_cal_check) < 0)
pdata->mis_cal_check = 0;
+ if (of_property_read_u32(np, "sec,encoded_enable",
+ &pdata->encoded_enable) < 0)
+ pdata->encoded_enable = 0;
+
+ pdata->grip_prescreen_mode = GRIP_PRESCREEN_MODE_2;
+ pdata->grip_prescreen_timeout = 120;
+ pdata->is_heatmap_enabled = false;
+ pdata->encoded_frame_counter = 0;
+ pdata->encoded_skip_counter = 0;
+
if (of_property_read_u32(np, "sec,heatmap_mode",
&pdata->heatmap_mode) < 0)
pdata->heatmap_mode = 0;
@@ -3274,20 +3966,28 @@ static int sec_ts_parse_dt(struct spi_device *client)
pdata->support_mt_pressure = true;
-#ifdef PAT_CONTROL
+ pdata->offload_id = 0;
+ if (of_property_read_u8_array(np, "sec,touch_offload_id",
+ offload_id, 4) == -EINVAL)
+ input_err(true, &client->dev,
+ "%s: Failed to read sec,touch_offload_id\n");
+ else {
+ pdata->offload_id = *(u32 *)offload_id;
+ input_info(true, &client->dev,
+ "%s: Offload device ID = \"%c%c%c%c\" / 0x%08X\n",
+ __func__, offload_id[0], offload_id[1], offload_id[2],
+ offload_id[3], pdata->offload_id);
+ }
+
+ if (of_property_read_u8(np, "sec,mm2px", &pdata->mm2px) < 0)
+ pdata->mm2px = 1;
input_info(true, &client->dev,
- "%s: buffer limit: %d, lcd_id:%06X, bringup:%d, FW:%s(%d), id:%d,%d, pat_function:%d mis_cal:%d dex:%d, gesture:%d\n",
- __func__, pdata->io_burstmax, lcdtype, pdata->bringup,
- pdata->firmware_name, count, pdata->tsp_id, pdata->tsp_icid,
- pdata->pat_function, pdata->mis_cal_check, pdata->support_dex,
- pdata->support_sidegesture);
-#else
+ "%s: mm2px %d\n", __func__, pdata->mm2px);
+
input_info(true, &client->dev,
- "%s: buffer limit: %d, lcd_id:%06X, bringup:%d, FW:%s(%d), id:%d,%d, dex:%d, gesture:%d\n",
- __func__, pdata->io_burstmax, lcdtype, pdata->bringup,
- pdata->firmware_name, count, pdata->tsp_id, pdata->tsp_icid,
- pdata->support_dex, pdata->support_sidegesture);
-#endif
+ "%s: io_burstmax: %d, bringup: %d, FW: %s, mis_cal_check: %d\n",
+ __func__, pdata->io_burstmax, pdata->bringup,
+ pdata->firmware_name, pdata->mis_cal_check);
return ret;
}
@@ -3320,7 +4020,7 @@ int sec_ts_read_information(struct sec_ts_data *ts)
}
input_info(true, &ts->client->dev,
- "%s: nTX:%d, nRX:%d, rY:%d, rX:%d\n",
+ "%s: nTX: %d, nRX: %d, rY: %d, rX: %d\n",
__func__, data[8], data[9],
(data[2] << 8) | data[3], (data[0] << 8) | data[1]);
@@ -3344,7 +4044,7 @@ int sec_ts_read_information(struct sec_ts_data *ts)
}
input_info(true, &ts->client->dev,
- "%s: STATUS : %X\n",
+ "%s: BOOT_STATUS: %X\n",
__func__, data[0]);
memset(data, 0x0, 4);
@@ -3357,7 +4057,7 @@ int sec_ts_read_information(struct sec_ts_data *ts)
}
input_info(true, &ts->client->dev,
- "%s: TOUCH STATUS : %02X, %02X, %02X, %02X\n",
+ "%s: TS_STATUS: %02X, %02X, %02X, %02X\n",
__func__, data[0], data[1], data[2], data[3]);
ret = sec_ts_read(ts, SEC_TS_CMD_SET_TOUCHFUNCTION,
(u8 *)&(ts->touch_functions), 2);
@@ -3369,7 +4069,7 @@ int sec_ts_read_information(struct sec_ts_data *ts)
}
input_info(true, &ts->client->dev,
- "%s: Functions : %02X\n",
+ "%s: Functions: %02X\n",
__func__, ts->touch_functions);
out:
@@ -3482,8 +4182,12 @@ static void sec_ts_set_input_prop(struct sec_ts_data *ts,
0, 0);
input_set_abs_params(dev, ABS_MT_POSITION_Y, 0, ts->plat_data->max_y,
0, 0);
- input_set_abs_params(dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
- input_set_abs_params(dev, ABS_MT_TOUCH_MINOR, 0, 255, 0, 0);
+ input_set_abs_params(dev, ABS_MT_TOUCH_MAJOR, 0,
+ 255 * ts->plat_data->mm2px,
+ 0, 0);
+ input_set_abs_params(dev, ABS_MT_TOUCH_MINOR, 0,
+ 255 * ts->plat_data->mm2px,
+ 0, 0);
input_set_abs_params(dev, ABS_MT_TOOL_TYPE, MT_TOOL_FINGER,
MT_TOOL_FINGER, 0, 0);
#ifdef ABS_MT_CUSTOM
@@ -3493,6 +4197,11 @@ static void sec_ts_set_input_prop(struct sec_ts_data *ts,
input_set_abs_params(dev, ABS_MT_PRESSURE, 0,
SEC_TS_PRESSURE_MAX, 0, 0);
+ /* Units are (-8192, 8192), representing the range between rotation
+ * 90 degrees to left and 90 degrees to the right.
+ */
+ input_set_abs_params(dev, ABS_MT_ORIENTATION, -8192, 8192, 0, 0);
+
if (propbit == INPUT_PROP_POINTER)
input_mt_init_slots(dev, MAX_SUPPORT_TOUCH_COUNT,
INPUT_MT_POINTER);
@@ -3519,7 +4228,7 @@ static int sec_ts_fw_init(struct sec_ts_data *ts)
__func__, ret);
else
input_info(true, &ts->client->dev,
- "%s: TOUCH DEVICE ID : %02X, %02X, %02X, %02X, %02X\n",
+ "%s: DEVICE ID: %02X, %02X, %02X, %02X, %02X\n",
__func__, deviceID[0], deviceID[1], deviceID[2],
deviceID[3], deviceID[4]);
@@ -3549,7 +4258,7 @@ static int sec_ts_fw_init(struct sec_ts_data *ts)
__func__, ret);
}
input_info(true, &ts->client->dev,
- "%s: TOUCH STATUS : %02X || %02X, %02X, %02X, %02X\n",
+ "%s: TOUCH STATUS: %02X || %02X, %02X, %02X, %02X\n",
__func__, data[0], data[1], data[2], data[3], data[4]);
if (data[0] == SEC_TS_STATUS_BOOT_MODE)
@@ -3658,6 +4367,43 @@ static void sec_ts_device_init(struct sec_ts_data *ts)
#endif
}
+static int sec_ts_heatmap_init(struct sec_ts_data *ts)
+{
+ int ret = 0;
+
+ if (ts->heatmap_init_done) {
+ input_info(true, &ts->client->dev, "%s: already init done!\n",
+ __func__);
+ return ret;
+ }
+
+ input_info(true, &ts->client->dev, "%s\n", __func__);
+#if IS_ENABLED(CONFIG_TOUCHSCREEN_HEATMAP)
+ /*
+ * Heatmap_probe must be called before irq routine is registered,
+ * because heatmap_read is called from the irq context.
+ * If the ISR runs before heatmap_probe is finished, it will invoke
+ * heatmap_read and cause NPE, since read_frame would not yet be set.
+ */
+ ts->v4l2.parent_dev = &ts->client->dev;
+ ts->v4l2.input_dev = ts->input_dev;
+ ts->v4l2.read_frame = read_heatmap_raw;
+ ts->v4l2.width = ts->tx_count;
+ ts->v4l2.height = ts->rx_count;
+ /* 120 Hz operation */
+ ts->v4l2.timeperframe.numerator = 1;
+ ts->v4l2.timeperframe.denominator = 120;
+ ret = heatmap_probe(&ts->v4l2);
+ if (ret == 0) {
+ ts->heatmap_init_done = true;
+ } else {
+ input_err(true, &ts->client->dev,
+ "%s: fail! ret %d\n", __func__, ret);
+ }
+#endif
+ return ret;
+}
+
#ifdef USE_CHARGER_WORK
static struct notifier_block sec_ts_psy_nb;
#endif
@@ -3682,6 +4428,14 @@ static int sec_ts_probe(struct spi_device *client)
return -EIO;
}
#else
+ if (client->controller->rt == false) {
+ client->rt = true;
+ ret = spi_setup(client);
+ if (ret < 0) {
+ input_err(true, &client->dev, "%s: setup SPI rt failed(%d)\n",
+ __func__, ret);
+ }
+ }
input_info(true, &client->dev, "%s: SPI interface(%d Hz)\n",
__func__, client->max_speed_hz);
#endif
@@ -3799,13 +4553,14 @@ static int sec_ts_probe(struct spi_device *client)
#endif
#if IS_ENABLED(CONFIG_TOUCHSCREEN_TBN)
- ts->tbn = tbn_init(&ts->client->dev);
- if (!ts->tbn) {
- input_err(true, &ts->client->dev,
- "%s: TBN initialization error\n", __func__);
+ if (register_tbn(&ts->tbn_register_mask)) {
ret = -ENODEV;
+ input_err(true, &ts->client->dev,
+ "%s: Failed to register tbn context.\n", __func__);
goto err_init_tbn;
}
+ input_info(true, &ts->client->dev, "%s: tbn_register_mask = %#x.\n",
+ __func__, ts->tbn_register_mask);
#endif
if (gpio_is_valid(ts->plat_data->tsp_id))
@@ -3880,6 +4635,12 @@ static int sec_ts_probe(struct spi_device *client)
sec_ts_delay(70);
ts->power_status = SEC_TS_STATE_POWER_ON;
ts->external_factory = false;
+ ts->heatmap_init_done = false;
+ ts->mutual_strength_heatmap.timestamp = 0;
+ ts->mutual_strength_heatmap.size_x = 0;
+ ts->mutual_strength_heatmap.size_y = 0;
+ ts->mutual_strength_heatmap.data = NULL;
+ ts->v4l2_mutual_strength_updated = false;
ret = sec_ts_wait_for_ready(ts, SEC_TS_ACK_BOOT_COMPLETE);
if (ret < 0) {
@@ -3891,18 +4652,32 @@ static int sec_ts_probe(struct spi_device *client)
input_err(true, &ts->client->dev,
"%s: could not read boot status. Assuming no device connected.\n",
__func__);
+ ret = -EPROBE_DEFER;
goto err_init;
}
- input_info(true, &ts->client->dev,
- "%s: Attempting to reflash the firmware. Boot status = 0x%02X\n",
- __func__, boot_status);
- if (boot_status != SEC_TS_STATUS_BOOT_MODE)
+ switch (boot_status) {
+ case SEC_TS_STATUS_BOOT_MODE:
input_err(true, &ts->client->dev,
- "%s: device is not in bootloader mode!\n",
- __func__);
-
- ts->is_fw_corrupted = true;
+ "%s: boot timeout(status %#x)! Reflash FW to recover.\n",
+ __func__, boot_status);
+ sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_FW_UPDATE, true);
+ ret = sec_ts_firmware_update_on_probe(ts, true);
+ sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_FW_UPDATE, false);
+ if (ret) {
+ ts->is_fw_corrupted = true;
+ ret = -EPROBE_DEFER;
+ goto err_init;
+ }
+ break;
+ case SEC_TS_STATUS_APP_MODE:
+ default:
+ input_err(true, &ts->client->dev,
+ "%s: boot timeout(status %#x)! Reset system to recover.\n",
+ __func__, boot_status);
+ sec_ts_system_reset(ts, RESET_MODE_HW, true, false);
+ break;
+ }
}
input_info(true, &client->dev, "%s: power enable\n", __func__);
@@ -3910,6 +4685,7 @@ static int sec_ts_probe(struct spi_device *client)
if (ts->is_fw_corrupted == false) {
switch (sec_ts_fw_init(ts)) {
case SEC_TS_ERR_INIT:
+ ret = -EPROBE_DEFER;
goto err_init;
case SEC_TS_ERR_ALLOC_FRAME:
goto err_allocate_frame;
@@ -3930,28 +4706,13 @@ static int sec_ts_probe(struct spi_device *client)
/* init motion filter mode */
ts->use_default_mf = 0;
ts->mf_state = SEC_TS_MF_FILTERED;
-#if IS_ENABLED(CONFIG_TOUCHSCREEN_HEATMAP)
- /*
- * Heatmap_probe must be called before irq routine is registered,
- * because heatmap_read is called from the irq context.
- * If the ISR runs before heatmap_probe is finished, it will invoke
- * heatmap_read and cause NPE, since read_frame would not yet be set.
- */
- ts->v4l2.parent_dev = &ts->client->dev;
- ts->v4l2.input_dev = ts->input_dev;
- ts->v4l2.read_frame = read_heatmap_raw;
- ts->v4l2.width = ts->tx_count;
- ts->v4l2.height = ts->rx_count;
- /* 120 Hz operation */
- ts->v4l2.timeperframe.numerator = 1;
- ts->v4l2.timeperframe.denominator = 120;
- ret = heatmap_probe(&ts->v4l2);
- if (ret) {
- input_err(true, &ts->client->dev,
- "%s: Heatmap probe failed\n", __func__);
- goto err_irq;
+
+ /* init heatmap */
+ if (ts->is_fw_corrupted == false) {
+ ret = sec_ts_heatmap_init(ts);
+ if (ret)
+ goto err_irq;
}
-#endif
input_info(true, &ts->client->dev, "%s: request_irq = %d\n", __func__,
client->irq);
@@ -3965,11 +4726,11 @@ static int sec_ts_probe(struct spi_device *client)
}
#if IS_ENABLED(CONFIG_TOUCHSCREEN_OFFLOAD)
- ts->offload.caps.touch_offload_major_version = 1;
- ts->offload.caps.touch_offload_minor_version = 0;
- /* ID equivalent to the 4-byte, little-endian string: '00r3' */
- ts->offload.caps.device_id =
- '3' << 24 | 'r' << 16 | '0' << 8 | '0' << 0;
+ ts->offload.caps.touch_offload_major_version =
+ TOUCH_OFFLOAD_INTERFACE_MAJOR_VERSION;
+ ts->offload.caps.touch_offload_minor_version =
+ TOUCH_OFFLOAD_INTERFACE_MINOR_VERSION;
+ ts->offload.caps.device_id = ts->plat_data->offload_id;
ts->offload.caps.display_width = ts->plat_data->max_x + 1;
ts->offload.caps.display_height = ts->plat_data->max_y + 1;
ts->offload.caps.tx_size = ts->tx_count;
@@ -3991,11 +4752,15 @@ static int sec_ts_probe(struct spi_device *client)
TOUCH_DATA_TYPE_COORD | TOUCH_DATA_TYPE_STRENGTH;
ts->offload.caps.touch_scan_types =
TOUCH_SCAN_TYPE_MUTUAL | TOUCH_SCAN_TYPE_SELF;
+ ts->offload.caps.context_channel_types =
+ CONTEXT_CHANNEL_TYPE_DRIVER_STATUS;
ts->offload.caps.continuous_reporting = true;
ts->offload.caps.noise_reporting = false;
ts->offload.caps.cancel_reporting = false;
+ ts->offload.caps.rotation_reporting = true;
ts->offload.caps.size_reporting = true;
+ ts->offload.caps.auto_reporting = false;
ts->offload.caps.filter_grip = true;
ts->offload.caps.filter_palm = true;
ts->offload.caps.num_sensitivity_settings = 1;
@@ -4092,7 +4857,8 @@ err_allocate_input_dev_pad:
input_free_device(ts->input_dev);
err_allocate_input_dev:
#if IS_ENABLED(CONFIG_TOUCHSCREEN_TBN)
- tbn_cleanup(ts->tbn);
+ if (ts->tbn_register_mask)
+ unregister_tbn(&ts->tbn_register_mask);
err_init_tbn:
#endif
@@ -4136,6 +4902,7 @@ error_allocate_pdata:
void sec_ts_unlocked_release_all_finger(struct sec_ts_data *ts)
{
int i;
+ s64 ms_delta;
for (i = 0; i < MAX_SUPPORT_TOUCH_COUNT; i++) {
input_mt_slot(ts->input_dev, i);
@@ -4149,22 +4916,22 @@ void sec_ts_unlocked_release_all_finger(struct sec_ts_data *ts)
SEC_TS_COORDINATE_ACTION_MOVE)) {
input_info(true, &ts->client->dev,
- "%s: [RA] tID:%d mc:%d tc:%d v:%02X%02X cal:%02X(%02X) id(%d,%d) p:%d\n",
+ "%s: [RA] tID: %d mc: %d tc: %u v: %02X%02X cal: %02X(%02X) id(%d,%d)\n",
__func__, i,
ts->coord[i].mcount, ts->touch_count,
ts->plat_data->img_version_of_ic[2],
ts->plat_data->img_version_of_ic[3],
ts->cal_status, ts->nv, ts->tspid_val,
- ts->tspicid_val, ts->coord[i].palm_count);
+ ts->tspicid_val);
- ktime_get_real_ts64(&ts->time_released[i]);
+ ts->coord[i].ktime_released = ktime_get();
+ ms_delta = ktime_ms_delta(ts->coord[i].ktime_released,
+ ts->coord[i].ktime_pressed);
+ if (ts->longest_duration < ms_delta)
+ ts->longest_duration = ms_delta;
- if (ts->time_longest <
- (ts->time_released[i].tv_sec -
- ts->time_pressed[i].tv_sec))
- ts->time_longest =
- (ts->time_released[i].tv_sec -
- ts->time_pressed[i].tv_sec);
+ /* special case to push into kfifo during release all fingers. */
+ sec_ts_kfifo_push_coord(ts, i);
}
#if IS_ENABLED(CONFIG_TOUCHSCREEN_OFFLOAD)
@@ -4172,11 +4939,10 @@ void sec_ts_unlocked_release_all_finger(struct sec_ts_data *ts)
ts->offload.coords[i].major = 0;
ts->offload.coords[i].minor = 0;
ts->offload.coords[i].pressure = 0;
+ ts->offload.coords[i].rotation = 0;
#endif
ts->coord[i].action = SEC_TS_COORDINATE_ACTION_RELEASE;
ts->coord[i].mcount = 0;
- ts->coord[i].palm_count = 0;
-
}
input_mt_slot(ts->input_dev, 0);
@@ -4204,7 +4970,6 @@ void sec_ts_unlocked_release_all_finger(struct sec_ts_data *ts)
#endif
input_report_key(ts->input_dev, KEY_HOMEPAGE, 0);
input_sync(ts->input_dev);
-
}
void sec_ts_locked_release_all_finger(struct sec_ts_data *ts)
@@ -4232,6 +4997,7 @@ static void sec_ts_reset_work(struct work_struct *work)
sec_ts_start_device(ts);
ts->reset_is_on_going = false;
+ ts->plat_data->is_heatmap_enabled = false;
sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_RESET, false);
}
@@ -4256,7 +5022,7 @@ void sec_ts_read_init_info(struct sec_ts_data *ts)
SEC_TS_NVM_OFFSET_PRESSURE_DELTA_CAL_COUNT);
input_info(true, &ts->client->dev,
- "%s: fac_nv:%02X, cal_count:%02X\n",
+ "%s: fac_nv: %02X, cal_count: %02X\n",
__func__, ts->nv, ts->cal_count);
#ifdef PAT_CONTROL
@@ -4341,10 +5107,11 @@ static void sec_ts_fw_update_work(struct work_struct *work)
if (ret == SEC_TS_ERR_NA) {
ts->is_fw_corrupted = false;
sec_ts_device_init(ts);
- } else
+ } else {
input_info(true, &ts->client->dev,
"%s: fail to sec_ts_fw_init 0x%x\n",
__func__, ret);
+ }
}
if (ts->is_fw_corrupted == false)
@@ -4586,7 +5353,8 @@ static int sec_ts_remove(struct spi_device *client)
ts->plat_data->power(ts, false);
#if IS_ENABLED(CONFIG_TOUCHSCREEN_TBN)
- tbn_cleanup(ts->tbn);
+ if (ts->tbn_register_mask)
+ unregister_tbn(&ts->tbn_register_mask);
#endif
if (gpio_is_valid(ts->plat_data->irq_gpio))
@@ -4603,6 +5371,7 @@ static int sec_ts_remove(struct spi_device *client)
#if IS_ENABLED(CONFIG_TOUCHSCREEN_HEATMAP)
kfree(ts->heatmap_buff);
+ kfree(ts->encoded_buff);
#endif
#ifdef USE_STIM_PAD
kfree(ts->gainTable);
@@ -4686,7 +5455,7 @@ int sec_ts_start_device(struct sec_ts_data *ts)
ts->touch_functions = ts->touch_functions |
SEC_TS_BIT_SETFUNC_COVER;
input_info(true, &ts->client->dev,
- "%s: cover cmd write type:%d, mode:%x, ret:%d",
+ "%s: cover cmd write type: %d, mode: %x, ret: %d",
__func__, ts->touch_functions,
ts->cover_cmd, ret);
} else {
@@ -4760,9 +5529,10 @@ static int sec_ts_pm_suspend(struct device *dev)
{
struct sec_ts_data *ts = dev_get_drvdata(dev);
- if (ts->bus_refmask)
+ if (ts->bus_refmask) {
input_info(true, &ts->client->dev,
"%s: bus_refmask 0x%X\n", __func__, ts->bus_refmask);
+ }
/* Flush work in case a suspend is in progress */
flush_workqueue(ts->event_wq);
@@ -4771,6 +5541,19 @@ static int sec_ts_pm_suspend(struct device *dev)
input_err(true, &ts->client->dev,
"%s: can't suspend because touch bus is in use!\n",
__func__);
+ if (ts->bus_refmask == SEC_TS_BUS_REF_BUGREPORT) {
+ s64 delta_ms = ktime_ms_delta(ktime_get(),
+ ts->bugreport_ktime_start);
+
+ if (delta_ms > 30 * MSEC_PER_SEC) {
+ sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_BUGREPORT, false);
+ pm_relax(&ts->client->dev);
+ ts->bugreport_ktime_start = 0;
+ input_err(true, &ts->client->dev,
+ "%s: force release SEC_TS_BUS_REF_BUGREPORT(delta: %lld)!\n",
+ __func__, delta_ms);
+ }
+ }
return -EBUSY;
}
@@ -4834,6 +5617,13 @@ static void sec_ts_suspend_work(struct work_struct *work)
int ret = 0;
input_info(true, &ts->client->dev, "%s\n", __func__);
+ input_info(true, &ts->client->dev, "%s: encoded skipped %d/%d\n",
+ __func__, ts->plat_data->encoded_skip_counter,
+ ts->plat_data->encoded_frame_counter);
+ if (ts->plat_data->grip_prescreen_mode != GRIP_PRESCREEN_OFF) {
+ input_info(true, &ts->client->dev, "%s: grip prescreened frames %d.\n",
+ __func__, sec_ts_ptflib_get_grip_prescreen_frames(ts));
+ }
mutex_lock(&ts->device_mutex);
@@ -4846,6 +5636,8 @@ static void sec_ts_suspend_work(struct work_struct *work)
return;
}
+ sec_ts_enable_fw_grip(ts, true);
+
/* Stop T-IC */
sec_ts_fix_tmode(ts, TOUCH_SYSTEM_MODE_SLEEP, TOUCH_MODE_STATE_STOP);
ret = sec_ts_write(ts, SEC_TS_CMD_CLEAR_EVENT_STACK, NULL, 0);
@@ -4866,25 +5658,34 @@ static void sec_ts_suspend_work(struct work_struct *work)
sec_set_switch_gpio(ts, SEC_SWITCH_GPIO_VALUE_SLPI_MASTER);
#if IS_ENABLED(CONFIG_TOUCHSCREEN_TBN)
- if (ts->tbn)
- tbn_release_bus(ts->tbn);
+ if (ts->tbn_register_mask)
+ tbn_release_bus(ts->tbn_register_mask);
#endif
mutex_unlock(&ts->device_mutex);
+
+ sec_ts_debug_dump(ts);
}
static void sec_ts_resume_work(struct work_struct *work)
{
struct sec_ts_data *ts = container_of(work, struct sec_ts_data,
resume_work);
+ u8 touch_mode[2] = {0};
int ret = 0;
input_info(true, &ts->client->dev, "%s\n", __func__);
+ ts->comm_err_count = 0;
+ ts->hw_reset_count = 0;
+ ts->longest_duration = 0;
+ ts->pressed_count = 0;
+ ts->palm_count = 0;
+ ts->wet_count = 0;
mutex_lock(&ts->device_mutex);
#if IS_ENABLED(CONFIG_TOUCHSCREEN_TBN)
- if (ts->tbn)
- tbn_request_bus(ts->tbn);
+ if (ts->tbn_register_mask)
+ tbn_request_bus(ts->tbn_register_mask);
#endif
sec_set_switch_gpio(ts, SEC_SWITCH_GPIO_VALUE_AP_MASTER);
@@ -4902,10 +5703,62 @@ static void sec_ts_resume_work(struct work_struct *work)
ts->power_status = SEC_TS_STATE_POWER_ON;
- ret = sec_ts_system_reset(ts);
- if (ret < 0)
+ ret = ts->sec_ts_read(ts, SEC_TS_CMD_CHG_SYSMODE, touch_mode,
+ sizeof(touch_mode));
+ if (ret < 0) {
input_err(true, &ts->client->dev,
- "%s: reset failed! ret %d\n", __func__, ret);
+ "%s: read touch mode failed(%d)\n",
+ __func__, ret);
+ ret = sec_ts_system_reset(ts, RESET_MODE_HW, false, false);
+ if (ret < 0) {
+ input_err(true, &ts->client->dev,
+ "%s: reset failed! ret %d\n", __func__, ret);
+ }
+ } else {
+ u8 power_mode = TO_TOUCH_MODE;
+ u8 state_manage_on = { STATE_MANAGE_ON };
+
+ input_info(true, &ts->client->dev,
+ "%s: before resume: mode %#x, state %#x.\n",
+ __func__, touch_mode[0], touch_mode[1]);
+
+ /* Enable Normal scan. */
+ ret = sec_ts_write(ts, SEC_TS_CMD_SET_POWER_MODE,
+ &power_mode, sizeof(power_mode));
+ if (ret < 0) {
+ input_err(true, &ts->client->dev,
+ "%s: set power mode failed(%d)\n",
+ __func__, ret);
+ ret = sec_ts_system_reset(ts, RESET_MODE_HW, false, false);
+ if (ret < 0) {
+ input_err(true, &ts->client->dev,
+ "%s: reset failed! ret %d\n", __func__, ret);
+ }
+ } else {
+ /* Wait at least 50 ms for mode change. */
+ sec_ts_delay(50);
+ }
+
+ ret = ts->sec_ts_read(ts, SEC_TS_CMD_CHG_SYSMODE, touch_mode,
+ sizeof(touch_mode));
+ if (ret < 0) {
+ input_err(true, &ts->client->dev,
+ "%s: read touch mode failed(%d)\n",
+ __func__, ret);
+ } else {
+ input_info(true, &ts->client->dev,
+ "%s: after resume: mode %#x, state %#x.\n",
+ __func__, touch_mode[0], touch_mode[1]);
+ }
+
+ ret = sec_ts_write(ts, SEC_TS_CMD_STATEMANAGE_ON, &state_manage_on,
+ sizeof(state_manage_on));
+ if (ret < 0) {
+ input_err(true, &ts->client->dev,
+ "%s: SEC_TS_CMD_STATEMANAGE_ON failed! ret %d\n",
+ __func__, ret);
+ }
+ }
if (ts->plat_data->enable_sync)
ts->plat_data->enable_sync(true);
@@ -4924,7 +5777,9 @@ static void sec_ts_resume_work(struct work_struct *work)
sec_ts_set_custom_library(ts);
#endif
- sec_ts_set_grip_type(ts, ONLY_EDGE_HANDLER);
+ ts->plat_data->is_heatmap_enabled = false;
+ ts->plat_data->encoded_frame_counter = 0;
+ ts->plat_data->encoded_skip_counter = 0;
if (ts->dex_mode) {
input_info(true, &ts->client->dev, "%s: set dex mode.\n",
@@ -4984,8 +5839,10 @@ static void sec_ts_resume_work(struct work_struct *work)
input_info(true, &ts->client->dev,
"applying touch_offload settings.\n");
- if (!ts->offload.config.filter_grip)
- sec_ts_enable_grip(ts, false);
+ if (ts->offload.config.filter_grip) {
+ sec_ts_enable_fw_grip(ts, false);
+ sec_ts_enable_ptflib(ts, true);
+ }
}
#endif
@@ -5006,14 +5863,18 @@ static void sec_ts_charger_work(struct work_struct *work)
u8 charger_mode = SEC_TS_BIT_CHARGER_MODE_NO;
bool usb_present = ts->usb_present;
bool wlc_online = ts->wlc_online;
+ bool force_wlc = ts->force_wlc;
+ const u64 debounce_ms = 500;
/* usb case */
- ret = power_supply_get_property(ts->usb_psy,
- POWER_SUPPLY_PROP_PRESENT, &prop);
- if (ret == 0) {
- usb_present = !!prop.intval;
- if (usb_present)
- charger_mode = SEC_TS_BIT_CHARGER_MODE_WIRE_CHARGER;
+ if (ts->usb_psy != NULL) {
+ ret = power_supply_get_property(ts->usb_psy,
+ POWER_SUPPLY_PROP_PRESENT, &prop);
+ if (ret == 0) {
+ usb_present = !!prop.intval;
+ if (usb_present)
+ charger_mode = SEC_TS_BIT_CHARGER_MODE_WIRE_CHARGER;
+ }
}
/* wlc case */
@@ -5029,29 +5890,42 @@ static void sec_ts_charger_work(struct work_struct *work)
}
}
- /* rtx case */
- /* ret = power_supply_get_property(ts->wireless_psy,
- POWER_SUPPLY_PROP_RTX, &prop); */
- if (ret == 0)
- pr_debug("%s: RTX %s", __func__,
- (!!prop.intval) ? "ON" : "OFF");
-
+ /*
+ * RTX case
+ * ret = power_supply_get_property(ts->wireless_psy,
+ * POWER_SUPPLY_PROP_RTX, &prop);
+ * if (ret == 0)
+ * pr_debug("%s: RTX %s", __func__,
+ * (!!prop.intval) ? "ON" : "OFF");
+ */
+
+ /* Check if any change for usb and wlc */
if (usb_present == ts->usb_present &&
- wlc_online == ts->wlc_online &&
- ts->keep_wlc_mode == false)
+ wlc_online == ts->wlc_online) {
+ input_dbg(true, &ts->client->dev,
+ "%s: usb_present(%d) and wlc_online(%d) no changed!",
+ __func__, usb_present, wlc_online);
return;
+ }
- /* keep wlc mode if usb plug in w/ wlc off case */
- if (ts->keep_wlc_mode) {
- input_info(true, &ts->client->dev,
- "keep wlc mode after usb plug in during wlc online");
+ /* Force wlc case */
+ if (usb_present &&
+ !wlc_online && ts->wlc_online &&
+ ktime_before(ts->wlc_changed_ktime,
+ ktime_add_ms(ts->usb_changed_ktime, debounce_ms))) {
+ force_wlc = true;
charger_mode = SEC_TS_BIT_CHARGER_MODE_WIRELESS_CHARGER;
+ input_info(true, &ts->client->dev,
+ "%s: force wlc mode if usb present during wlc online.",
+ __func__);
+ } else {
+ force_wlc = false;
}
input_info(true, &ts->client->dev,
- "%s: keep_wlc_mode %d, USB(%d->%d), WLC(%d->%d), charger_mode(%#x->%#x)",
+ "%s: force_wlc(%d->%d), usb_present(%d->%d), wlc_online(%d->%d), charger_mode(%#x->%#x)",
__func__,
- ts->keep_wlc_mode,
+ ts->force_wlc, force_wlc,
ts->usb_present, usb_present,
ts->wlc_online, wlc_online,
ts->charger_mode, charger_mode);
@@ -5082,7 +5956,7 @@ static void sec_ts_charger_work(struct work_struct *work)
/* update final charger state */
ts->wlc_online = wlc_online;
ts->usb_present = usb_present;
- ts->keep_wlc_mode = false;
+ ts->force_wlc = force_wlc;
}
#endif
@@ -5195,6 +6069,13 @@ static void panel_bridge_disable(struct drm_bridge *bridge)
struct sec_ts_data *ts =
container_of(bridge, struct sec_ts_data, panel_bridge);
+ if (bridge->encoder && bridge->encoder->crtc) {
+ const struct drm_crtc_state *crtc_state = bridge->encoder->crtc->state;
+
+ if (drm_atomic_crtc_effectively_active(crtc_state))
+ return;
+ }
+
pr_debug("%s\n", __func__);
sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SCREEN_ON, false);
}
@@ -5271,7 +6152,6 @@ static void unregister_panel_bridge(struct drm_bridge *bridge)
static int sec_ts_psy_cb(struct notifier_block *nb,
unsigned long val, void *data)
{
- u64 debounce = 500;
struct sec_ts_data *ts = container_of(nb, struct sec_ts_data, psy_nb);
pr_debug("%s: val %lu", __func__, val);
@@ -5283,22 +6163,11 @@ static int sec_ts_psy_cb(struct notifier_block *nb,
return NOTIFY_OK;
if (ts->usb_psy == data) {
- ts->usb_changed_timestamp = ktime_get();
- if (ts->wlc_online) {
- input_dbg(true, &ts->client->dev,
- "%s: ignore this usb_psy changed during wlc_online!",
- __func__);
- return NOTIFY_OK;
- }
+ ts->usb_changed_ktime = ktime_get();
}
if (ts->wireless_psy != NULL && ts->wireless_psy == data) {
- /* keep wlc mode after usb plug in during wlc online */
- if (ts->wlc_online == true &&
- ts->usb_present == false &&
- ktime_before(ktime_get(),
- ktime_add_ms(ts->usb_changed_timestamp, debounce)))
- ts->keep_wlc_mode = true;
+ ts->wlc_changed_ktime = ktime_get();
}
if (ts->power_status == SEC_TS_STATE_POWER_ON)
@@ -5361,7 +6230,7 @@ static int __init sec_ts_init(void)
{
#ifdef CONFIG_BATTERY_SAMSUNG
if (lpcharge == 1) {
- pr_err("%s %s: Do not load driver due to : lpm %d\n",
+ pr_err("%s %s: Do not load driver due to lpm %d\n",
SECLOG, __func__, lpcharge);
return -ENODEV;
}
diff --git a/sec_ts.h b/sec_ts.h
index 589424b..f4ef114 100644
--- a/sec_ts.h
+++ b/sec_ts.h
@@ -24,17 +24,18 @@
#include <linux/spi/spi.h>
#include <linux/input.h>
#if IS_ENABLED(CONFIG_TOUCHSCREEN_HEATMAP)
-#include <linux/input/heatmap.h>
+#include <heatmap.h>
#endif
#include <linux/input/mt.h>
#if IS_ENABLED(CONFIG_TOUCHSCREEN_OFFLOAD)
-#include <linux/input/touch_offload.h>
+#include <touch_offload.h>
#endif
#include "sec_cmd.h"
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/kernel.h>
+#include <linux/kfifo.h>
#include <linux/module.h>
#include <drm/drm_bridge.h>
#include <drm/drm_device.h>
@@ -60,7 +61,7 @@
#endif
#if IS_ENABLED(CONFIG_TOUCHSCREEN_TBN)
-#include <linux/input/touch_bus_negotiator.h>
+#include <touch_bus_negotiator.h>
#endif
#define SEC_TS_NAME "sec_ts"
@@ -558,6 +559,13 @@ enum {
**/
};
+enum RESET_MODE {
+ RESET_MODE_NA = 0x00,
+ RESET_MODE_SW = 0x01,
+ RESET_MODE_HW = 0x02,
+ RESET_MODE_AUTO = (RESET_MODE_SW | RESET_MODE_HW),
+};
+
enum CUSTOMLIB_EVENT_TYPE {
CUSTOMLIB_EVENT_TYPE_SPAY = 0x04,
CUSTOMLIB_EVENT_TYPE_PRESSURE_TOUCHED = 0x05,
@@ -579,7 +587,8 @@ enum {
SEC_TS_BUS_REF_INPUT_DEV = 0x10,
SEC_TS_BUS_REF_READ_INFO = 0x20,
SEC_TS_BUS_REF_SYSFS = 0x40,
- SEC_TS_BUS_REF_FORCE_ACTIVE = 0x80
+ SEC_TS_BUS_REF_FORCE_ACTIVE = 0x80,
+ SEC_TS_BUS_REF_BUGREPORT = 0x100
};
enum {
@@ -650,6 +659,23 @@ enum {
HEATMAP_FULL = 2
};
+enum {
+ GRIP_PRESCREEN_OFF = 0,
+ GRIP_PRESCREEN_MODE_1 = 1,
+ GRIP_PRESCREEN_MODE_2 = 2,
+ GRIP_PRESCREEN_MODE_3 = 3
+};
+
+enum {
+ GRIP_PRESCREEN_TIMEOUT_MIN = 0,
+ GRIP_PRESCREEN_TIMEOUT_MAX = 480
+};
+
+enum {
+ ENCODED_ENABLE_OFF = 0,
+ ENCODED_ENABLE_ON = 1
+};
+
/* Motion filter finite state machine (FSM) states
* SEC_TS_MF_FILTERED - default coordinate filtering
* SEC_TS_MF_UNFILTERED - unfiltered single-touch coordinates
@@ -675,6 +701,13 @@ struct heatmap_report {
/* data is in BE order; order should be enforced after data is read */
strength_t data[LOCAL_HEATMAP_WIDTH * LOCAL_HEATMAP_HEIGHT];
} __packed;
+
+struct heatmap_data {
+ ktime_t timestamp;
+ uint16_t size_x;
+ uint16_t size_y;
+ uint8_t *data;
+} __packed;
#endif
#define TEST_MODE_MIN_MAX false
@@ -749,12 +782,33 @@ struct sec_ts_gesture_status {
/* status id for sec_ts event */
#define SEC_TS_EVENT_STATUS_ID_HOPPING 0x33
#define SEC_TS_EVENT_STATUS_ID_REPORT_RATE 0x34
+#define SEC_TS_EVENT_STATUS_ID_VSYNC 0x35
#define SEC_TS_EVENT_STATUS_ID_NOISE 0x64
#define SEC_TS_EVENT_STATUS_ID_WLC 0x66
#define SEC_TS_EVENT_STATUS_ID_GRIP 0x69
+#define SEC_TS_EVENT_STATUS_ID_FOD 0x6B
#define SEC_TS_EVENT_STATUS_ID_PALM 0x70
/* 8 byte */
+struct sec_ts_fod_event {
+ struct {
+ u8 type;
+ u8 id;
+ u8 status;
+ u8 x_b7_b0;
+ union {
+ struct {
+ u8 y_b11_b8:4;
+ u8 x_b11_b8:4;
+ };
+ u8 x_y_b11_b8;
+ };
+ u8 y_b7_b0;
+ u8 reserved[2];
+ };
+} __packed;
+
+/* 8 byte */
struct sec_ts_event_status {
union {
struct {
@@ -817,12 +871,16 @@ struct sec_ts_coordinate {
u8 glove_flag;
u8 touch_height;
u16 mcount;
- u8 major;
- u8 minor;
+ u16 major;
+ u16 minor;
bool palm;
- int palm_count;
u8 left_event;
bool grip;
+ /* for debug purpose. */
+ u16 x_pressed; /* x coord on first down timing. */
+ u16 y_pressed; /* y coord on first down timing. */
+ ktime_t ktime_pressed;
+ ktime_t ktime_released;
};
struct sec_ts_data {
@@ -852,11 +910,7 @@ struct sec_ts_data {
* in CLOCK_MONOTONIC
**/
- struct timespec64 time_pressed[MAX_SUPPORT_TOUCH_COUNT +
- MAX_SUPPORT_HOVER_COUNT];
- struct timespec64 time_released[MAX_SUPPORT_TOUCH_COUNT +
- MAX_SUPPORT_HOVER_COUNT];
- long time_longest;
+ s64 longest_duration; /* ms unit */
u8 lowpower_mode;
u8 lowpower_status;
@@ -871,7 +925,7 @@ struct sec_ts_data {
struct completion bus_resumed;
struct completion boot_completed;
- int touch_count;
+ unsigned int touch_count; /* active touch slot(s). */
int tx_count;
int rx_count;
int io_burstmax;
@@ -910,9 +964,14 @@ struct sec_ts_data {
u8 print_format;
u8 ms_frame_type;
u8 ss_frame_type;
+ int heatmap_dump;
#if IS_ENABLED(CONFIG_TOUCHSCREEN_HEATMAP)
struct v4l2_heatmap v4l2;
+ struct heatmap_data mutual_strength_heatmap;
strength_t *heatmap_buff;
+ strength_t *encoded_buff;
+ bool heatmap_init_done;
+ bool v4l2_mutual_strength_updated;
#endif
#if IS_ENABLED(CONFIG_TOUCHSCREEN_OFFLOAD)
@@ -989,16 +1048,25 @@ struct sec_ts_data {
int tune_fix_ver;
bool external_factory;
+ int report_rate;
+ int vsync;
int wet_mode;
unsigned char ito_test[4]; /* ito panel tx/rx chanel */
unsigned char check_multi;
unsigned int multi_count; /* multi touch count */
+ unsigned int palm_count;
unsigned int wet_count; /* wet mode count */
unsigned int dive_count; /* dive mode count */
- unsigned int comm_err_count; /* comm error count */
- unsigned int io_err_count; /* io error count */
- unsigned int checksum_result; /* checksum result */
+ unsigned int comm_err_count; /* comm error count */
+ unsigned int io_err_count; /* io error count */
+ unsigned int hw_reset_count;
+ /*
+ * accumulated count of pressed
+ * touch from resume to suspend.
+ */
+ unsigned int pressed_count;
+ unsigned int checksum_result; /* checksum result */
unsigned char module_id[4];
unsigned int all_finger_count;
unsigned int all_force_count;
@@ -1016,7 +1084,14 @@ struct sec_ts_data {
short pressure_right;
u8 pressure_user_level;
#endif
- int debug;
+ union {
+ u32 debug;
+ struct {
+ u32 debug_events : 1;
+ u32 debug_status : 1;
+ u32 debug_reserved : 30;
+ };
+ };
int fs_postcal_mean;
@@ -1047,7 +1122,7 @@ struct sec_ts_data {
bool grips_leaved_once;
#if IS_ENABLED(CONFIG_TOUCHSCREEN_TBN)
- struct tbn_context *tbn;
+ u32 tbn_register_mask;
#endif
struct power_supply *wireless_psy;
@@ -1055,8 +1130,11 @@ struct sec_ts_data {
struct notifier_block psy_nb;
bool wlc_online;
bool usb_present;
- bool keep_wlc_mode;
- ktime_t usb_changed_timestamp;
+ bool force_wlc;
+ ktime_t usb_changed_ktime;
+ ktime_t wlc_changed_ktime;
+
+ ktime_t bugreport_ktime_start;
int (*sec_ts_write)(struct sec_ts_data *ts, u8 reg,
u8 *data, int len);
@@ -1086,6 +1164,8 @@ struct sec_ts_data {
};
struct sec_ts_plat_data {
+ int fod_x;
+ int fod_y;
int max_x;
int max_y;
unsigned int irq_gpio;
@@ -1095,6 +1175,12 @@ struct sec_ts_plat_data {
int bringup;
int mis_cal_check;
int heatmap_mode;
+ int grip_prescreen_mode;
+ int grip_prescreen_timeout;
+ bool is_heatmap_enabled;
+ int encoded_enable;
+ int encoded_frame_counter;
+ int encoded_skip_counter;
#ifdef PAT_CONTROL
int pat_function;
int afe_base;
@@ -1119,7 +1205,7 @@ struct sec_ts_plat_data {
void (*enable_sync)(bool on);
int tsp_icid;
int tsp_id;
- int tsp_vsync;
+ int vsync_gpio;
int switch_gpio;
int reset_gpio;
@@ -1130,13 +1216,21 @@ struct sec_ts_plat_data {
struct drm_panel *panel;
u32 initial_panel_index;
+ u32 offload_id;
+
+ /* convert mm to pixel for major and minor */
+ u8 mm2px;
};
+void sec_ts_debug_dump(struct sec_ts_data *ts);
int sec_ts_stop_device(struct sec_ts_data *ts);
int sec_ts_start_device(struct sec_ts_data *ts);
-int sec_ts_hw_reset(struct sec_ts_data *ts);
-int sec_ts_sw_reset(struct sec_ts_data *ts);
-int sec_ts_system_reset(struct sec_ts_data *ts);
+int sec_ts_hw_reset(struct sec_ts_data *ts, bool wait_for_done);
+int sec_ts_sw_reset(struct sec_ts_data *ts, bool wait_for_done);
+int sec_ts_system_reset(struct sec_ts_data *ts,
+ enum RESET_MODE mode,
+ bool wait_for_done,
+ bool sense_on);
int sec_ts_set_lowpowermode(struct sec_ts_data *ts, u8 mode);
int sec_ts_firmware_update_on_probe(struct sec_ts_data *ts, bool force_update);
int sec_ts_firmware_update_on_hidden_menu(struct sec_ts_data *ts,
diff --git a/sec_ts_fn.c b/sec_ts_fn.c
index 26771a6..1a07174 100644
--- a/sec_ts_fn.c
+++ b/sec_ts_fn.c
@@ -246,7 +246,7 @@ static void set_palm_detection_enable(void *device_data)
struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec);
char buff[4] = { 0 };
u8 para = 0x0;
- u8 ret = 0;
+ int ret;
input_info(true, &ts->client->dev,
"%s: %d\n", __func__, sec->cmd_param[0]);
@@ -292,7 +292,7 @@ static void set_grip_detection_enable(void *device_data)
struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec);
char buff[4] = { 0 };
u8 para = 0x0;
- u8 ret = 0;
+ int ret;
input_info(true, &ts->client->dev,
"%s: %d\n", __func__, sec->cmd_param[0]);
@@ -338,7 +338,7 @@ static void set_wet_mode_enable(void *device_data)
struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec);
char buff[4] = { 0 };
u8 para = 0x0;
- u8 ret = 0;
+ int ret;
input_info(true, &ts->client->dev,
"%s: %d\n", __func__, sec->cmd_param[0]);
@@ -384,7 +384,7 @@ static void set_noise_mode_enable(void *device_data)
struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec);
char buff[4] = { 0 };
u8 para = 0x0;
- u8 ret = 0;
+ int ret;
input_info(true, &ts->client->dev,
"%s: %d\n", __func__, sec->cmd_param[0]);
@@ -430,7 +430,7 @@ static void set_continuous_report_enable(void *device_data)
struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec);
char buff[4] = { 0 };
u8 para = 0x0;
- u8 ret = 0;
+ int ret;
input_info(true, &ts->client->dev,
"%s: %d\n", __func__, sec->cmd_param[0]);
@@ -519,7 +519,7 @@ static ssize_t scrub_pos_show(struct device *dev,
"%s: scrub_id: %d\n", __func__, ts->scrub_id);
#else
input_info(true, &ts->client->dev,
- "%s: scrub_id: %d, X:%d, Y:%d\n", __func__,
+ "%s: scrub_id: %d, X: %d, Y: %d\n", __func__,
ts->scrub_id, ts->scrub_x, ts->scrub_y);
#endif
snprintf(buff, sizeof(buff), "%d %d %d",
@@ -730,7 +730,7 @@ static ssize_t holding_time_store(struct device *dev,
struct sec_cmd_data *sec = dev_get_drvdata(dev);
struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec);
- ts->time_longest = 0;
+ ts->longest_duration = 0;
input_info(true, &ts->client->dev, "%s: clear\n", __func__);
@@ -743,10 +743,10 @@ static ssize_t holding_time_show(struct device *dev,
struct sec_cmd_data *sec = dev_get_drvdata(dev);
struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec);
- input_info(true, &ts->client->dev, "%s: %ld\n", __func__,
- ts->time_longest);
+ input_info(true, &ts->client->dev, "%s: %lld ms\n",
+ __func__, ts->longest_duration);
- return snprintf(buf, SEC_CMD_BUF_SIZE, "%ld", ts->time_longest);
+ return snprintf(buf, SEC_CMD_BUF_SIZE, "%lld ms", ts->longest_duration);
}
static ssize_t all_touch_count_show(struct device *dev,
@@ -756,7 +756,7 @@ static ssize_t all_touch_count_show(struct device *dev,
struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec);
input_info(true, &ts->client->dev,
- "%s: touch:%d, force:%d, aod:%d, spay:%d\n", __func__,
+ "%s: touch: %d, force: %d, aod: %d, spay: %d\n", __func__,
ts->all_finger_count, ts->all_force_count,
ts->all_aod_tap_count, ts->all_spay_count);
@@ -788,7 +788,7 @@ static ssize_t z_value_show(struct device *dev,
struct sec_cmd_data *sec = dev_get_drvdata(dev);
struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec);
- input_info(true, &ts->client->dev, "%s: max:%d, min:%d, avg:%d\n",
+ input_info(true, &ts->client->dev, "%s: max: %d, min: %d, avg: %d\n",
__func__, ts->max_z_value, ts->min_z_value, ts->sum_z_value);
if (ts->all_finger_count)
@@ -1052,6 +1052,204 @@ static ssize_t heatmap_mode_show(struct device *dev,
#endif
}
+/* sysfs file node to store grip prescreen mode
+ * "echo cmd > grip_prescreen_mode" to change
+ * Possible commands:
+ * 0 = GRIP_PRESCREEN_OFF
+ * 1 = GRIP_PRESCREEN_MODE_1
+ * 2 = GRIP_PRESCREEN_MODE_2
+ * 3 = GRIP_PRESCREEN_MODE_3
+ */
+static ssize_t grip_prescreen_mode_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sec_cmd_data *sec = dev_get_drvdata(dev);
+ struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec);
+ struct sec_ts_plat_data *pdata = ts->plat_data;
+ int result;
+ int val;
+
+ result = kstrtoint(buf, 10, &val);
+ if (result < 0 || val < GRIP_PRESCREEN_OFF ||
+ val > GRIP_PRESCREEN_MODE_3) {
+ input_err(true, &ts->client->dev,
+ "%s: Invalid input.\n", __func__);
+ return -EINVAL;
+ }
+
+ pdata->grip_prescreen_mode = val;
+
+ return count;
+}
+
+static ssize_t grip_prescreen_mode_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct sec_cmd_data *sec = dev_get_drvdata(dev);
+ struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec);
+ const struct sec_ts_plat_data *pdata = ts->plat_data;
+
+ return scnprintf(buf, PAGE_SIZE, "%d\n",
+ pdata->grip_prescreen_mode);
+}
+
+/* sysfs file node to store grip prescreen timeout
+ * "echo timeout > grip_prescreen_timeout" to change
+ * Possible timeout range:
+ * GRIP_PRESCREEN_TIMEOUT_MIN ~ GRIP_PRESCREEN_TIMEOUT_MAX
+ */
+static ssize_t grip_prescreen_timeout_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sec_cmd_data *sec = dev_get_drvdata(dev);
+ struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec);
+ struct sec_ts_plat_data *pdata = ts->plat_data;
+ int result;
+ int val;
+
+ result = kstrtoint(buf, 10, &val);
+ if (result < 0 || val < GRIP_PRESCREEN_TIMEOUT_MIN ||
+ val > GRIP_PRESCREEN_TIMEOUT_MAX) {
+ input_err(true, &ts->client->dev,
+ "%s: Invalid input.\n", __func__);
+ return -EINVAL;
+ }
+
+ pdata->grip_prescreen_timeout = val;
+
+ return count;
+}
+
+static ssize_t grip_prescreen_timeout_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct sec_cmd_data *sec = dev_get_drvdata(dev);
+ struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec);
+ const struct sec_ts_plat_data *pdata = ts->plat_data;
+
+ return scnprintf(buf, PAGE_SIZE, "%d\n",
+ pdata->grip_prescreen_timeout);
+}
+
+/* sysfs file node to store encoded_enable control
+ * "echo cmd > encoded_enable" to change
+ * Possible commands:
+ * 0 = ENCODED_ENABLE_OFF
+ * 1 = ENCODED_ENABLE_ON
+ */
+static ssize_t encoded_enable_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+#if IS_ENABLED(CONFIG_TOUCHSCREEN_HEATMAP)
+ struct sec_cmd_data *sec = dev_get_drvdata(dev);
+ struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec);
+ struct sec_ts_plat_data *pdata = ts->plat_data;
+ int result;
+ int val;
+
+ result = kstrtoint(buf, 10, &val);
+ if (result < 0 || val < ENCODED_ENABLE_OFF ||
+ val > ENCODED_ENABLE_ON) {
+ input_err(true, &ts->client->dev,
+ "%s: Invalid input.\n", __func__);
+ return -EINVAL;
+ }
+ pdata->encoded_enable = val;
+
+ return count;
+#else
+ return 0;
+#endif
+}
+
+static ssize_t encoded_enable_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+#if IS_ENABLED(CONFIG_TOUCHSCREEN_HEATMAP)
+ struct sec_cmd_data *sec = dev_get_drvdata(dev);
+ struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec);
+ const struct sec_ts_plat_data *pdata = ts->plat_data;
+
+ return scnprintf(buf, PAGE_SIZE, "%d\n", pdata->encoded_enable);
+#else
+ return scnprintf(buf, PAGE_SIZE, "N/A\n");
+#endif
+}
+
+
+/* sysfs file node to dump heatmap
+ * "echo cmd > heatmap_dump" to change
+ * Possible commands:
+ * 0 = disable
+ * 1 = enable
+ */
+static ssize_t heatmap_dump_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+#if IS_ENABLED(CONFIG_TOUCHSCREEN_HEATMAP)
+ struct sec_cmd_data *sec = dev_get_drvdata(dev);
+ struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec);
+ int result;
+ int val;
+
+ result = kstrtoint(buf, 10, &val);
+ if (result < 0 || val < 0 || val > 1) {
+ input_err(true, &ts->client->dev,
+ "%s: Invalid input.\n", __func__);
+ return -EINVAL;
+ }
+ ts->heatmap_dump = val;
+ return count;
+#else
+ return 0;
+#endif
+}
+
+static ssize_t heatmap_dump_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+#if IS_ENABLED(CONFIG_TOUCHSCREEN_HEATMAP)
+ struct sec_cmd_data *sec = dev_get_drvdata(dev);
+ struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec);
+ struct sec_ts_plat_data *pdata = ts->plat_data;
+ int x, y, max_x, max_y, index = 0;
+
+ index += scnprintf(buf + index, PAGE_SIZE - index,
+ "heatmap dump(mode %d) %s\n",
+ pdata->heatmap_mode,
+ (ts->heatmap_dump) ? "ENABLE" : "DISABLE");
+
+ if (!ts->heatmap_dump)
+ return index;
+
+ max_x = ts->tx_count;
+ max_y = ts->rx_count;
+
+ for (y = 0 ; y < max_y ; y++) {
+ for (x = 0 ; x < max_x ; x++) {
+ index += scnprintf(buf + index,
+ PAGE_SIZE - index,
+ " %3d,",
+ ts->v4l2.frame[y * max_x + x]);
+ if (x == max_x - 1)
+ index += scnprintf(buf + index,
+ PAGE_SIZE - index, "\n");
+ }
+ }
+
+ return index;
+#else
+ return scnprintf(buf, PAGE_SIZE, "N/A\n");
+#endif
+}
+
static ssize_t fw_version_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -1136,7 +1334,7 @@ static ssize_t status_show(struct device *dev,
goto out;
}
written += scnprintf(buf + written, PAGE_SIZE - written,
- "BOOT STATUS: 0x%02X\n", data[0]);
+ "Boot status: %#x\n", data[0]);
memset(data, 0x0, 4);
ret = ts->sec_ts_read(ts, SEC_TS_READ_TS_STATUS, data, 4);
@@ -1147,7 +1345,7 @@ static ssize_t status_show(struct device *dev,
goto out;
}
written += scnprintf(buf + written, PAGE_SIZE - written,
- "TOUCH STATUS: 0x%02X, 0x%02X, 0x%02X, 0x%02X\n",
+ "Touch status: %#x, %#x, %#x, %#x\n",
data[0], data[1], data[2], data[3]);
memset(data, 0x0, 2);
@@ -1159,8 +1357,17 @@ static ssize_t status_show(struct device *dev,
goto out;
}
written += scnprintf(buf + written, PAGE_SIZE - written,
- "Functions: 0x%02X, 0x%02X\n", data[0], data[1]);
-
+ "Functions: %#x, %#x\n", data[0], data[1]);
+ written += scnprintf(buf + written, PAGE_SIZE - written,
+ "Charger mode: %#x\n", ts->charger_mode);
+ written += scnprintf(buf + written, PAGE_SIZE - written,
+ "Wet mode: %d\n", ts->wet_mode);
+ written += scnprintf(buf + written, PAGE_SIZE - written,
+ "Fingers#: %d\n", ts->touch_count);
+ written += scnprintf(buf + written, PAGE_SIZE - written,
+ "Report rate: %d\n", ts->report_rate);
+ written += scnprintf(buf + written, PAGE_SIZE - written,
+ "Vsync: %d\n", ts->vsync);
out:
sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false);
@@ -1182,6 +1389,10 @@ static DEVICE_ATTR_RW(pressure_enable);
static DEVICE_ATTR_RO(get_lp_dump);
static DEVICE_ATTR_RO(force_recal_count);
static DEVICE_ATTR_RW(heatmap_mode);
+static DEVICE_ATTR_RW(grip_prescreen_mode);
+static DEVICE_ATTR_RW(grip_prescreen_timeout);
+static DEVICE_ATTR_RW(encoded_enable);
+static DEVICE_ATTR_RW(heatmap_dump);
static DEVICE_ATTR_RO(fw_version);
static DEVICE_ATTR_RO(status);
@@ -1203,6 +1414,10 @@ static struct attribute *cmd_attributes[] = {
&dev_attr_get_lp_dump.attr,
&dev_attr_force_recal_count.attr,
&dev_attr_heatmap_mode.attr,
+ &dev_attr_grip_prescreen_mode.attr,
+ &dev_attr_grip_prescreen_timeout.attr,
+ &dev_attr_encoded_enable.attr,
+ &dev_attr_heatmap_dump.attr,
&dev_attr_fw_version.attr,
&dev_attr_status.attr,
NULL,
@@ -4622,7 +4837,7 @@ int get_tsp_nvm_data(struct sec_ts_data *ts, u8 offset)
}
input_info(true, &ts->client->dev,
- "%s: offset:%u data:%02X\n", __func__, offset, buff[0]);
+ "%s: offset: %u data: %02X\n", __func__, offset, buff[0]);
out_nvm:
ret = ts->sec_ts_write(ts, SEC_TS_CMD_SENSE_ON, NULL, 0);
@@ -4646,7 +4861,7 @@ int get_tsp_nvm_data_by_size(struct sec_ts_data *ts, u8 offset,
return -ENOMEM;
input_info(true, &ts->client->dev,
- "%s: offset:%u, length:%d, size:%d\n",
+ "%s: offset: %u, length: %d, size: %d\n",
__func__, offset, length, sizeof(data));
/* SENSE OFF -> CELAR EVENT STACK -> READ NV -> SENSE ON */
@@ -4876,12 +5091,12 @@ static void get_tsp_test_result(void *device_data)
result = (struct sec_ts_test_result *)buff;
input_info(true, &ts->client->dev,
- "%s: [0x%X][0x%X] M:%d, M:%d, A:%d, A:%d\n",
+ "%s: [0x%X][0x%X] M: %d, M: %d, A: %d, A: %d\n",
__func__, *result->data, buff[0],
result->module_result, result->module_count,
result->assy_result, result->assy_count);
- snprintf(buff, sizeof(buff), "M:%s, M:%d, A:%s, A:%d",
+ snprintf(buff, sizeof(buff), "M: %s, M: %d, A: %s, A: %d",
result->module_result == 0 ? "NONE" :
result->module_result == 1 ? "FAIL" : "PASS",
result->module_count,
@@ -6243,7 +6458,7 @@ static void run_force_pressure_calibration(void *device_data)
ts->pressure_cal_base = get_tsp_nvm_data(ts,
SEC_TS_NVM_OFFSET_PRESSURE_BASE_CAL_COUNT);
- input_info(true, &ts->client->dev, "%s: count:%d\n",
+ input_info(true, &ts->client->dev, "%s: count: %d\n",
__func__, ts->pressure_cal_base);
enable_irq(ts->client->irq);
@@ -6658,7 +6873,7 @@ static void set_pressure_strength(void *device_data)
SEC_TS_NVM_OFFSET_PRESSURE_DELTA_CAL_COUNT);
input_info(true, &ts->client->dev,
- "%s: count:%d\n", __func__, ts->pressure_cal_delta);
+ "%s: count: %d\n", __func__, ts->pressure_cal_delta);
sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false);
return;
@@ -7395,7 +7610,7 @@ static void set_aod_rect(void *device_data)
sec_cmd_set_default_result(sec);
- input_info(true, &ts->client->dev, "%s: w:%d, h:%d, x:%d, y:%d\n",
+ input_info(true, &ts->client->dev, "%s: w: %d, h: %d, x: %d, y: %d\n",
__func__, sec->cmd_param[0], sec->cmd_param[1],
sec->cmd_param[2], sec->cmd_param[3]);
@@ -7469,7 +7684,7 @@ static void get_aod_rect(void *device_data)
rect_data[i] = (data[i * 2 + 1] & 0xFF) << 8 |
(data[i * 2] & 0xFF);
- input_info(true, &ts->client->dev, "%s: w:%d, h:%d, x:%d, y:%d\n",
+ input_info(true, &ts->client->dev, "%s: w: %d, h: %d, x: %d, y: %d\n",
__func__,
rect_data[0], rect_data[1], rect_data[2], rect_data[3]);
@@ -7874,12 +8089,13 @@ static void force_touch_active(void *device_data)
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec);
int active, ret;
+ u16 bus_ref = SEC_TS_BUS_REF_FORCE_ACTIVE;
sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true);
sec_cmd_set_default_result(sec);
- if (sec->cmd_param[0] < 0 || sec->cmd_param[0] > 1) {
+ if (sec->cmd_param[0] < 0 || sec->cmd_param[0] > 2) {
sec_cmd_set_cmd_result(sec, "NG", 2);
sec_cmd_set_cmd_exit(sec);
sec->cmd_state = SEC_CMD_STATUS_FAIL;
@@ -7888,15 +8104,29 @@ static void force_touch_active(void *device_data)
return;
}
- active = sec->cmd_param[0];
+ /* Specific case for bugreport. */
+ if (sec->cmd_param[0] == 2) {
+ bus_ref = SEC_TS_BUS_REF_BUGREPORT;
+ active = (sec->cmd_param[1]) ? true : false;
+ if (active) {
+ sec_ts_debug_dump(ts);
+ ts->bugreport_ktime_start = ktime_get();
+ } else {
+ ts->bugreport_ktime_start = 0;
+ }
+ } else {
+ active = sec->cmd_param[0];
+ }
input_info(true, &ts->client->dev,
- "%s: %s\n", __func__, active ? "enable" : "disable");
+ "%s: %s %#x\n", __func__, active ? "enable" : "disable",
+ bus_ref);
+
if (active)
pm_stay_awake(&ts->client->dev);
else
pm_relax(&ts->client->dev);
- ret = sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_FORCE_ACTIVE, active);
+ ret = sec_ts_set_bus_ref(ts, bus_ref, active);
if (ret == 0) {
sec_cmd_set_cmd_result(sec, "OK", 2);
sec->cmd_state = SEC_CMD_STATUS_OK;
@@ -8250,9 +8480,18 @@ static void set_touch_mode(void *device_data)
break;
case 7:
input_info(true, &ts->client->dev,
- "%s: param = %d, do touch system reset\n",
- __func__, sec->cmd_param[0]);
- sec_ts_system_reset(ts);
+ "%s: param = %d %d, do touch system reset\n",
+ __func__, sec->cmd_param[0], sec->cmd_param[1]);
+ switch (sec->cmd_param[1]) {
+ case RESET_MODE_SW:
+ sec_ts_system_reset(ts, RESET_MODE_SW, true, true);
+ break;
+ case RESET_MODE_HW:
+ sec_ts_system_reset(ts, RESET_MODE_HW, true, true);
+ break;
+ default:
+ sec_ts_system_reset(ts, RESET_MODE_AUTO, true, true);
+ }
break;
case 8:
input_info(true, &ts->client->dev,
@@ -8400,7 +8639,7 @@ int sec_ts_run_rawdata_type(struct sec_ts_data *ts, struct sec_cmd_data *sec)
ts->tsp_dump_lock = 1;
input_info(true, &ts->client->dev,
- "%s: start (wet:%d)##\n",
+ "%s: start (wet: %d)##\n",
__func__, ts->wet_mode);
@@ -8444,7 +8683,7 @@ int sec_ts_run_rawdata_type(struct sec_ts_data *ts, struct sec_cmd_data *sec)
if (ret < 0)
input_info(true, &ts->client->dev,
- "%s: mutual %d : error ## ret:%d\n",
+ "%s: mutual %d : error ## ret: %d\n",
__func__, sec->cmd_param[0], ret);
else
#ifdef USE_SPEC_CHECK
@@ -8491,7 +8730,7 @@ int sec_ts_run_rawdata_type(struct sec_ts_data *ts, struct sec_cmd_data *sec)
max, &spec_check);
if (ret < 0)
input_info(true, &ts->client->dev,
- "%s: self %d : error ## ret:%d\n",
+ "%s: self %d : error ## ret: %d\n",
__func__, sec->cmd_param[0], ret);
else
#ifdef USE_SPEC_CHECK
@@ -8586,11 +8825,11 @@ int sec_ts_run_rawdata_type(struct sec_ts_data *ts, struct sec_cmd_data *sec)
sec_ts_release_tmode(ts);
out:
- input_info(true, &ts->client->dev, "%s: ito : %02X %02X %02X %02X\n",
+ input_info(true, &ts->client->dev, "%s: ito: %02X %02X %02X %02X\n",
__func__, ts->ito_test[0], ts->ito_test[1]
, ts->ito_test[2], ts->ito_test[3]);
- input_info(true, &ts->client->dev, "%s: done (wet:%d)##\n",
+ input_info(true, &ts->client->dev, "%s: done (wet: %d)##\n",
__func__, ts->wet_mode);
ts->tsp_dump_lock = 0;
@@ -8670,7 +8909,7 @@ void sec_ts_run_rawdata_all(struct sec_ts_data *ts, bool full_read)
ts->tsp_dump_lock = 1;
input_info(true, &ts->client->dev,
- "%s: start (wet:%d)##\n",
+ "%s: start (wet: %d)##\n",
__func__, ts->wet_mode);
ret = sec_ts_fix_tmode(ts, TOUCH_SYSTEM_MODE_TOUCH,
@@ -8693,7 +8932,7 @@ void sec_ts_run_rawdata_all(struct sec_ts_data *ts, bool full_read)
&spec_check);
if (ret < 0)
input_info(true, &ts->client->dev,
- "%s: mutual %d : error ## ret:%d\n",
+ "%s: mutual %d : error ## ret: %d\n",
__func__, test_type[i], ret);
else
#ifdef USE_SPEC_CHECK
@@ -8712,7 +8951,7 @@ void sec_ts_run_rawdata_all(struct sec_ts_data *ts, bool full_read)
max, &spec_check);
if (ret < 0)
input_info(true, &ts->client->dev,
- "%s: self %d : error ## ret:%d\n",
+ "%s: self %d : error ## ret: %d\n",
__func__, test_type[i], ret);
else
#ifdef USE_SPEC_CHECK
@@ -8779,11 +9018,11 @@ void sec_ts_run_rawdata_all(struct sec_ts_data *ts, bool full_read)
sec_ts_release_tmode(ts);
out:
- input_info(true, &ts->client->dev, "%s: ito : %02X %02X %02X %02X\n",
+ input_info(true, &ts->client->dev, "%s: ito: %02X %02X %02X %02X\n",
__func__, ts->ito_test[0], ts->ito_test[1]
, ts->ito_test[2], ts->ito_test[3]);
- input_info(true, &ts->client->dev, "%s: done (wet:%d)##\n",
+ input_info(true, &ts->client->dev, "%s: done (wet: %d)##\n",
__func__, ts->wet_mode);
ts->tsp_dump_lock = 0;
diff --git a/sec_ts_fw.c b/sec_ts_fw.c
index 54e0cd5..7810438 100644
--- a/sec_ts_fw.c
+++ b/sec_ts_fw.c
@@ -104,14 +104,36 @@ static int sec_ts_enter_fw_mode(struct sec_ts_data *ts)
return 1;
}
-int sec_ts_hw_reset(struct sec_ts_data *ts)
+int sec_ts_wait_for_reset_done(struct sec_ts_data *ts)
{
+ int ret = 0;
+
+ if (completion_done(&ts->bus_resumed) &&
+ ts->probe_done == true) {
+ if (!completion_done(&ts->boot_completed) &&
+ wait_for_completion_timeout(&ts->boot_completed,
+ msecs_to_jiffies(200) == 0))
+ ret = -ETIME;
+ } else {
+ ret = sec_ts_wait_for_ready_with_count(ts,
+ SEC_TS_ACK_BOOT_COMPLETE, 10);
+ }
+
+ return ret;
+}
+
+int sec_ts_hw_reset(struct sec_ts_data *ts, bool wait_for_done)
+{
+ int ret = 0;
int reset_gpio = ts->plat_data->reset_gpio;
- input_info(true, &ts->client->dev, "%s\n", __func__);
+ input_info(true, &ts->client->dev, "%s: wait_for_done %d.\n",
+ __func__, wait_for_done);
+ if (wait_for_done)
+ reinit_completion(&ts->boot_completed);
if (!gpio_is_valid(reset_gpio)) {
- input_err(true, &ts->client->dev, "%s: invalid gpio %d\n",
+ input_err(true, &ts->client->dev, "%s: invalid gpio %d.\n",
__func__, reset_gpio);
return -EINVAL;
}
@@ -119,135 +141,104 @@ int sec_ts_hw_reset(struct sec_ts_data *ts)
gpio_set_value(reset_gpio, 0);
sec_ts_delay(10);
gpio_set_value(reset_gpio, 1);
- /* wait 70 ms at least from bootloader to applicateion mode */
+
+ /* Wait 70 ms at least from bootloader to applicateion mode. */
sec_ts_delay(70);
- return 0;
+ if (wait_for_done) {
+ ret = sec_ts_wait_for_reset_done(ts);
+ if (!ret)
+ input_info(true, &ts->client->dev,
+ "%s: done.\n", __func__);
+ else
+ input_err(true, &ts->client->dev,
+ "%s: hw_reset time out!\n", __func__);
+ complete_all(&ts->boot_completed);
+ }
+
+ return ret;
}
-int sec_ts_sw_reset(struct sec_ts_data *ts)
+int sec_ts_sw_reset(struct sec_ts_data *ts, bool wait_for_done)
{
- int ret;
+ int ret = 0;
- input_info(true, &ts->client->dev, "%s\n", __func__);
+ input_info(true, &ts->client->dev, "%s: wait_for_done %d.\n",
+ __func__, wait_for_done);
+ if (wait_for_done)
+ reinit_completion(&ts->boot_completed);
ret = ts->sec_ts_write(ts, SEC_TS_CMD_SW_RESET, NULL, 0);
if (ret < 0) {
input_err(true, &ts->client->dev,
- "%s: write fail, sw_reset\n", __func__);
- return 0;
+ "%s: failed to write sw_reset.\n", __func__);
+ return -EIO;
}
- /* wait 70 ms at least from bootloader to applicateion mode */
+ /* Wait 70 ms at least from bootloader to applicateion mode. */
sec_ts_delay(70);
- ret = sec_ts_wait_for_ready(ts, SEC_TS_ACK_BOOT_COMPLETE);
- if (ret < 0) {
- input_err(true, &ts->client->dev, "%s: time out\n", __func__);
- return 0;
- }
-
- input_info(true, &ts->client->dev, "%s: sw_reset\n", __func__);
+ if (wait_for_done) {
+ ret = sec_ts_wait_for_reset_done(ts);
+ if (!ret)
+ input_info(true, &ts->client->dev,
+ "%s: done.\n", __func__);
+ else
+ input_err(true, &ts->client->dev,
+ "%s: sw_reset time out!\n", __func__);
- /* Sense_on */
- ret = ts->sec_ts_write(ts, SEC_TS_CMD_SENSE_ON, NULL, 0);
- if (ret < 0) {
- input_err(true, &ts->client->dev,
- "%s: write fail, Sense_on\n", __func__);
- return 0;
+ complete_all(&ts->boot_completed);
}
return ret;
}
-int sec_ts_system_reset(struct sec_ts_data *ts)
+int sec_ts_system_reset(struct sec_ts_data *ts,
+ enum RESET_MODE mode,
+ bool wait_for_done,
+ bool sense_on)
{
- int ret = -1;
+ int ret = 0;
- reinit_completion(&ts->boot_completed);
- ret = ts->sec_ts_write(ts, SEC_TS_CMD_SW_RESET, NULL, 0);
- if (ret < 0)
- input_err(true, &ts->client->dev, "%s: write fail, sw_reset\n",
- __func__);
- else {
- /* wait 70 ms at least from bootloader to applicateion mode */
- sec_ts_delay(70);
- if (completion_done(&ts->bus_resumed) &&
- ts->probe_done == true) {
- if (!completion_done(&ts->boot_completed) &&
- wait_for_completion_timeout(&ts->boot_completed,
- msecs_to_jiffies(200) == 0))
- ret = -ETIME;
- } else
- /* Normally it should not happen with any retry.
- * But, if happened, retry less time to wait ack
- */
- ret = sec_ts_wait_for_ready_with_count(ts,
- SEC_TS_ACK_BOOT_COMPLETE, 10);
+ input_info(true, &ts->client->dev,
+ "%s: mode %d, wait_for_done %d, sense_on %d.\n",
+ __func__, mode, wait_for_done, sense_on);
- if (ret < 0)
+ if (mode & RESET_MODE_SW) {
+ ret = sec_ts_sw_reset(ts, wait_for_done);
+ if (ret)
input_err(true, &ts->client->dev,
- "%s: sw_reset time out!\n", __func__);
+ "%s: sw reset failed.");
else
- input_info(true,
- &ts->client->dev, "%s: sw_reset done\n",
- __func__);
+ goto sw_reset_done;
}
- if (ret < 0) {
- if (!gpio_is_valid(ts->plat_data->reset_gpio)) {
+ if (mode & RESET_MODE_HW) {
+ if (ret)
input_err(true, &ts->client->dev,
- "%s: reset gpio is unavailable!\n", __func__);
- goto err_system_reset;
- }
-
- input_err(true, &ts->client->dev,
- "%s: sw_reset failed or time out, try hw_reset to recover!\n",
- __func__);
- ret = sec_ts_hw_reset(ts);
- if (ret) {
+ "%s: sw_reset failed or time out, try hw_reset to recover!\n",
+ __func__);
+ ret = sec_ts_hw_reset(ts, wait_for_done);
+ if (ret)
input_err(true, &ts->client->dev,
- "%s: hw_reset failed\n", __func__);
- goto err_system_reset;
- }
-
- if (completion_done(&ts->bus_resumed) &&
- ts->probe_done == true) {
- if (!completion_done(&ts->boot_completed) &&
- wait_for_completion_timeout(&ts->boot_completed,
- msecs_to_jiffies(200) == 0))
- ret = -ETIME;
- } else
- ret = sec_ts_wait_for_ready_with_count(ts,
- SEC_TS_ACK_BOOT_COMPLETE, 10);
+ "%s: hw reset failed.");
+ }
+sw_reset_done:
+ /* Sense on. */
+ if (sense_on) {
+ ret = ts->sec_ts_write(ts, SEC_TS_CMD_SENSE_ON, NULL, 0);
if (ret < 0) {
- input_err(true,
- &ts->client->dev, "%s: hw_reset time out\n",
+ input_err(true, &ts->client->dev,
+ "%s: failed to write sense_on.\n",
__func__);
- goto err_system_reset;
}
- input_info(true, &ts->client->dev, "%s: hw_reset done\n",
- __func__);
- }
-
- /* Sense_on */
- ret = ts->sec_ts_write(ts, SEC_TS_CMD_SENSE_ON, NULL, 0);
- if (ret < 0) {
- input_err(true, &ts->client->dev, "%s: write fail, Sense_on\n",
- __func__);
- goto err_system_reset;
}
- /* initialize wet status */
+ /* Initialize wet status. */
ts->wet_mode = 0;
ts->wet_count = 0;
- return 0;
-
-err_system_reset:
-
- complete_all(&ts->boot_completed);
return ret;
}
@@ -281,21 +272,21 @@ static void sec_ts_save_version_of_bin(struct sec_ts_data *ts,
ts->plat_data->config_version_of_bin[0] =
((fw_hd->para_ver >> 0) & 0xff);
- input_info(true, &ts->client->dev, "%s: img_ver of bin = %x.%x.%x.%x\n",
+ input_info(true, &ts->client->dev, "%s: img_ver of bin: %x.%x.%x.%x\n",
__func__,
ts->plat_data->img_version_of_bin[0],
ts->plat_data->img_version_of_bin[1],
ts->plat_data->img_version_of_bin[2],
ts->plat_data->img_version_of_bin[3]);
- input_info(true, &ts->client->dev, "%s: core_ver of bin = %x.%x.%x.%x\n",
+ input_info(true, &ts->client->dev, "%s: core_ver of bin: %x.%x.%x.%x\n",
__func__,
ts->plat_data->core_version_of_bin[0],
ts->plat_data->core_version_of_bin[1],
ts->plat_data->core_version_of_bin[2],
ts->plat_data->core_version_of_bin[3]);
- input_info(true, &ts->client->dev, "%s: config_ver of bin = %x.%x.%x.%x\n",
+ input_info(true, &ts->client->dev, "%s: config_ver of bin: %x.%x.%x.%x\n",
__func__,
ts->plat_data->config_version_of_bin[0],
ts->plat_data->config_version_of_bin[1],
@@ -318,7 +309,7 @@ static int sec_ts_save_version_of_ic(struct sec_ts_data *ts)
return -EIO;
}
input_info(true, &ts->client->dev,
- "%s: IC Image version info : %x.%x.%x.%x\n",
+ "%s: IC Image version info: %x.%x.%x.%x\n",
__func__, img_ver[0], img_ver[1], img_ver[2], img_ver[3]);
ts->plat_data->img_version_of_ic[0] = img_ver[0];
@@ -334,7 +325,7 @@ static int sec_ts_save_version_of_ic(struct sec_ts_data *ts)
return -EIO;
}
input_info(true, &ts->client->dev,
- "%s: IC Core version info : %x.%x.%x.%x,\n",
+ "%s: IC Core version info: %x.%x.%x.%x,\n",
__func__, core_ver[0], core_ver[1], core_ver[2], core_ver[3]);
ts->plat_data->core_version_of_ic[0] = core_ver[0];
@@ -350,7 +341,7 @@ static int sec_ts_save_version_of_ic(struct sec_ts_data *ts)
return -EIO;
}
input_info(true, &ts->client->dev,
- "%s: IC config version info : %x.%x.%x.%x\n",
+ "%s: IC config version info: %x.%x.%x.%x\n",
__func__, config_ver[0], config_ver[1],
config_ver[2], config_ver[3]);
@@ -506,7 +497,7 @@ static bool sec_ts_limited_flashpagewrite(struct sec_ts_data *ts,
ret = ts->sec_ts_write_burst_heap(ts, tCmd, 1 + copy_cur);
if (ret < 0)
input_err(true, &ts->client->dev,
- "%s: failed, ret:%d\n", __func__, ret);
+ "%s: failed, ret: %d\n", __func__, ret);
copy_size += copy_cur;
copy_left -= copy_cur;
@@ -832,13 +823,13 @@ static int sec_ts_firmware_update(struct sec_ts_data *ts, const u8 *data,
return -1;
}
- input_err(true, &ts->client->dev, "%s: num_chunk : %d\n",
+ input_info(true, &ts->client->dev, "%s: num_chunk: %d\n",
__func__, fw_hd->num_chunk);
for (i = 0; i < fw_hd->num_chunk; i++) {
fw_ch = (fw_chunk *)fd;
- input_err(true, &ts->client->dev,
+ input_info(true, &ts->client->dev,
"%s: [%d] 0x%08X, 0x%08X, 0x%08X, 0x%08X\n",
__func__, i, fw_ch->signature, fw_ch->addr,
fw_ch->size, fw_ch->reserved);
@@ -861,7 +852,7 @@ static int sec_ts_firmware_update(struct sec_ts_data *ts, const u8 *data,
fd += fw_ch->size;
}
- sec_ts_sw_reset(ts);
+ sec_ts_system_reset(ts, RESET_MODE_SW, true, true);
#ifdef PAT_CONTROL
if (restore_cal) {
@@ -1182,7 +1173,7 @@ int sec_ts_firmware_update_on_probe(struct sec_ts_data *ts, bool force_update)
ts->cal_status = sec_ts_read_calibration_report(ts);
input_info(true, &ts->client->dev,
- "%s: initial firmware update %s, cal:%X\n",
+ "%s: initial firmware update %s, cal: %X\n",
__func__, fw_path, ts->cal_status);
/* Loading Firmware */
@@ -1378,7 +1369,7 @@ static int sec_ts_load_fw_from_ffu(struct sec_ts_data *ts)
disable_irq(ts->client->irq);
input_info(true, ts->dev,
- "%s: Load firmware : %s\n", __func__, fw_path);
+ "%s: Load firmware: %s\n", __func__, fw_path);
/* Loading Firmware */
if (request_firmware(&fw_entry, fw_path, &ts->client->dev) != 0) {
diff --git a/sec_ts_only_vendor.c b/sec_ts_only_vendor.c
index d4a740b..205e801 100644
--- a/sec_ts_only_vendor.c
+++ b/sec_ts_only_vendor.c
@@ -415,7 +415,7 @@ static ssize_t sec_ts_enter_recovery_store(struct device *dev,
ret = kstrtoul(buf, 10, &on);
if (ret != 0) {
- input_err(true, &ts->client->dev, "%s: failed to read:%d\n",
+ input_err(true, &ts->client->dev, "%s: failed to read: %d\n",
__func__, ret);
return -EINVAL;
}