summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Chang <changmark@google.com>2021-04-01 15:29:19 +0800
committerMark Chang <changmark@google.com>2021-04-06 13:51:12 +0800
commitaa71ff13976a3ac8aa3e30887cb28433880f475d (patch)
tree56fe1a683667634954247a04d3de872c91ce5421
parentb14f9d30fb76bf1e6ade5cbd49950dbc0a4ee088 (diff)
downloadsec_touch-aa71ff13976a3ac8aa3e30887cb28433880f475d.tar.gz
touch/sec: support encoded heatmap in custom library.
Bug: 182246865 Test: Verified encoded heatmap with locally built ROM. Signed-off-by: Mark Chang <changmark@google.com> Change-Id: I97132cad3ea1486d0bfc4974284caa03f163355d
-rw-r--r--sec_ts.c235
-rw-r--r--sec_ts.h7
-rw-r--r--sec_ts_fn.c50
3 files changed, 288 insertions, 4 deletions
diff --git a/sec_ts.c b/sec_ts.c
index 5f4ce12..1be3784 100644
--- a/sec_ts.c
+++ b/sec_ts.c
@@ -1103,6 +1103,118 @@ 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;
+}
+
+static int sec_ts_ptflib_rle_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;
+
+ for (i = 0; i < in_array_size; i++) {
+ u16 curr_word = in_array[i];
+ if ((curr_word & ESCAPE_MASK) == ESCAPE_BIT) {
+ u16 repetition = (curr_word & ~ESCAPE_MASK) - 1;
+ if (out_array_size + repetition > out_array_max_size) {
+ input_err(true, &ts->client->dev,
+ "%s: decoding failed at %d.\n",
+ __func__, i);
+ return -1;
+ }
+ for (j = 0; j < repetition; j++) {
+ *out_array++ = prev_word;
+ out_array_size++;
+ }
+ } else {
+ if (out_array_size + 1 > out_array_max_size) {
+ input_err(true, &ts->client->dev,
+ "%s: decoding failed at %d.\n",
+ __func__, i);
+ return -1;
+ }
+ *out_array++ = curr_word;
+ out_array_size++;
+ prev_word = curr_word;
+ }
+ }
+
+ return out_array_size;
+}
+
static void sec_ts_reinit(struct sec_ts_data *ts)
{
u8 w_data[2] = {0x00, 0x00};
@@ -1965,6 +2077,102 @@ static void sec_ts_populate_coordinate_channel(struct sec_ts_data *ts,
}
}
+#define PTFLIB_ENCODED_COUNTER_OFFSET_LSB 0xA8
+#define PTFLIB_ENCODED_COUNTER_OFFSET_MSB 0x00
+#define PTFLIB_ENCODED_DATA_OFFSET_LSB 0xAE
+#define PTFLIB_ENCODED_DATA_OFFSET_MSB 0x00
+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;
+ u8 r_data[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ u16 encoded_data_size = 0;
+ int i;
+ int x;
+ int y;
+ int ret = 0;
+ 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);
+
+ r_data[0] = PTFLIB_ENCODED_COUNTER_OFFSET_LSB;
+ r_data[1] = PTFLIB_ENCODED_COUNTER_OFFSET_MSB;
+ ret = sec_ts_read_from_customlib(ts, r_data, sizeof(r_data));
+ if (ret < 0) {
+ input_err(true, &ts->client->dev,
+ "%s: Read customlib's data size failed\n",
+ __func__);
+ return -EIO;
+ }
+
+ heatmap_array_len = mutual_strength->tx_size * mutual_strength->rx_size;
+ encoded_counter = le32_to_cpup((uint32_t *) r_data);
+ encoded_data_size = le16_to_cpup((uint16_t *) &r_data[4]);
+
+ if (encoded_counter == 0 || encoded_data_size == 0 ||
+ encoded_data_size > heatmap_array_len * 2) {
+ input_err(true, &ts->client->dev,
+ "%s: Invalid encoded data size %d (%d)\n",
+ __func__, encoded_data_size, encoded_counter);
+ return -EIO;
+ }
+
+ if (!ts->encoded_buff) {
+ ts->encoded_buff = kmalloc(heatmap_array_len * 2, GFP_KERNEL);
+ if (!ts->encoded_buff) {
+ input_err(true, &ts->client->dev,
+ "%s: kmalloc for encoded_buff failed.\n",
+ __func__);
+ return -ENOMEM;
+ } else {
+ input_info(true, &ts->client->dev,
+ "%s: kmalloc for encoded_buff was successful.\n",
+ __func__);
+ }
+ }
+
+ /* Read encoded heatmap from customlib. */
+ *((u8 *) ts->encoded_buff) = PTFLIB_ENCODED_DATA_OFFSET_LSB;
+ *(((u8 *) ts->encoded_buff) + 1) = PTFLIB_ENCODED_DATA_OFFSET_MSB;
+ ret = sec_ts_read_from_customlib(ts, (u8 *) ts->encoded_buff,
+ encoded_data_size);
+ if (ret < 0) {
+ input_err(true, &ts->client->dev,
+ "%s: Read encoded data (size=%d) failed.\n",
+ __func__, encoded_data_size);
+ return -EIO;
+ }
+
+ decoded_size = sec_ts_ptflib_rle_decoder(
+ ts, (u16 *) ts->encoded_buff, encoded_data_size / 2,
+ (u16 *) ts->heatmap_buff, heatmap_array_len);
+ if (decoded_size != heatmap_array_len) {
+ input_info(true, &ts->client->dev,
+ "%s: Decoding data failed (decoded_size=%d).",
+ __func__, decoded_size);
+ 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];
+ }
+ }
+
+ return 0;
+}
+
static void sec_ts_populate_mutual_channel(struct sec_ts_data *ts,
struct touch_offload_frame *frame,
int channel)
@@ -2179,6 +2387,8 @@ static void sec_ts_populate_frame(struct sec_ts_data *ts,
{
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;
@@ -2190,12 +2400,21 @@ 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);
+ }
}
}
@@ -2224,6 +2443,9 @@ int sec_ts_enable_grip(struct sec_ts_data *ts, bool enable)
final_result = ret;
}
+ if (!enable)
+ sec_ts_ptflib_reinit(ts);
+
return final_result;
}
@@ -3270,6 +3492,10 @@ 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;
+
if (of_property_read_u32(np, "sec,heatmap_mode",
&pdata->heatmap_mode) < 0)
pdata->heatmap_mode = 0;
@@ -4621,6 +4847,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);
diff --git a/sec_ts.h b/sec_ts.h
index 5a4ec78..2414238 100644
--- a/sec_ts.h
+++ b/sec_ts.h
@@ -650,6 +650,11 @@ enum {
HEATMAP_FULL = 2
};
+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
@@ -914,6 +919,7 @@ struct sec_ts_data {
#if IS_ENABLED(CONFIG_TOUCHSCREEN_HEATMAP)
struct v4l2_heatmap v4l2;
strength_t *heatmap_buff;
+ strength_t *encoded_buff;
#endif
#if IS_ENABLED(CONFIG_TOUCHSCREEN_OFFLOAD)
@@ -1104,6 +1110,7 @@ struct sec_ts_plat_data {
int bringup;
int mis_cal_check;
int heatmap_mode;
+ int encoded_enable;
#ifdef PAT_CONTROL
int pat_function;
int afe_base;
diff --git a/sec_ts_fn.c b/sec_ts_fn.c
index fa63c1f..8c3cc69 100644
--- a/sec_ts_fn.c
+++ b/sec_ts_fn.c
@@ -1052,6 +1052,54 @@ static ssize_t heatmap_mode_show(struct device *dev,
#endif
}
+/* 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:
@@ -1256,6 +1304,7 @@ 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(encoded_enable);
static DEVICE_ATTR_RW(heatmap_dump);
static DEVICE_ATTR_RO(fw_version);
static DEVICE_ATTR_RO(status);
@@ -1278,6 +1327,7 @@ static struct attribute *cmd_attributes[] = {
&dev_attr_get_lp_dump.attr,
&dev_attr_force_recal_count.attr,
&dev_attr_heatmap_mode.attr,
+ &dev_attr_encoded_enable.attr,
&dev_attr_heatmap_dump.attr,
&dev_attr_fw_version.attr,
&dev_attr_status.attr,