summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordavidycchen <davidycchen@google.com>2021-12-20 17:13:30 +0800
committerdavidycchen <davidycchen@google.com>2021-12-21 18:25:59 +0800
commitf2bfef998a7497e947a4381f96abe9e789d781d1 (patch)
tree378131f0b4e1f29f4aef1ef0695722d5109d23b3
parent96d884a4c6120e4a8e837f02f27079f0d993521d (diff)
downloadsynaptics_touch-f2bfef998a7497e947a4381f96abe9e789d781d1.tar.gz
synaptics: synaptics: update driver version to 0118
Support two more testing - PID$12: Abs. Raw - PID$16: Trans Cap. Raw Correct the sequence of suspend-reset especially RESET_ON_RESUME enabled. Sample code to parse the custom gesture data. Enable RESET_ON_RESUME in default. Bug: 211379827 Signed-off-by: davidycchen <davidycchen@google.com> Change-Id: I888d0c68aa53020eb0e153105920b0fed133d8cb
-rw-r--r--syna_tcm2.c103
-rw-r--r--syna_tcm2.h6
-rw-r--r--syna_tcm2_sysfs.c10
-rw-r--r--syna_tcm2_testing.c313
-rw-r--r--syna_tcm2_testing_limits.h100
-rw-r--r--tcm/synaptics_touchcom_core_dev.h5
-rw-r--r--tcm/synaptics_touchcom_core_v1.c4
-rw-r--r--tcm/synaptics_touchcom_func_reflash.c12
-rw-r--r--tcm/synaptics_touchcom_func_romboot.c54
-rw-r--r--tcm/synaptics_touchcom_func_touch.c7
10 files changed, 566 insertions, 48 deletions
diff --git a/syna_tcm2.c b/syna_tcm2.c
index a77bf58..2a11b05 100644
--- a/syna_tcm2.c
+++ b/syna_tcm2.c
@@ -128,6 +128,11 @@ static void syna_dev_reset_detected_cb(void *callback_data)
return;
}
+#ifdef RESET_ON_RESUME
+ if (tcm->pwr_state != PWR_ON)
+ return;
+#endif
+
if (ATOMIC_GET(tcm->helper.task) == HELP_NONE) {
ATOMIC_SET(tcm->helper.task, HELP_RESET_DETECTED);
@@ -157,7 +162,7 @@ static void syna_dev_helper_work(struct work_struct *work)
switch (task) {
case HELP_RESET_DETECTED:
- LOGI("Reset caught, device mode 0x%x\n", tcm->tcm_dev->dev_mode);
+ LOGD("Reset caught (device mode:0x%x)\n", tcm->tcm_dev->dev_mode);
break;
default:
break;
@@ -324,23 +329,63 @@ static int syna_dev_parse_custom_gesture_cb(const unsigned char code,
struct syna_tcm *tcm = (struct syna_tcm *)callback_data;
unsigned int data;
unsigned int bits;
+ unsigned int offset = *report_offset;
+ struct custom_gesture_data {
+ unsigned short x;
+ unsigned short y;
+ unsigned char major;
+ unsigned char minor;
+ } g_pos;
bits = config[(*config_offset)++];
- syna_tcm_get_touch_data(report, report_size, *report_offset, bits, &data);
- switch (data) {
- case GESTURE_SINGLE_TAP:
- LOGI("Gesture single tap detected\n");
- break;
- case GESTURE_LONG_PRESS:
- LOGI("Gesture long press detected\n");
- break;
- default:
- LOGW("Unknown gesture id %d\n", data);
- break;
- }
+ if (code == TOUCH_REPORT_GESTURE_ID) {
+ syna_tcm_get_touch_data(report, report_size, offset, bits, &data);
+
+ switch (data) {
+ case GESTURE_SINGLE_TAP:
+ LOGI("Gesture single tap detected\n");
+ break;
+ case GESTURE_LONG_PRESS:
+ LOGI("Gesture long press detected\n");
+ break;
+ default:
+ LOGW("Unknown gesture id %d\n", data);
+ break;
+ }
+
+ *report_offset += bits;
+
+ } else if (code == TOUCH_REPORT_GESTURE_DATA) {
+ if (bits != (sizeof(struct custom_gesture_data) * 8)) {
+ LOGE("Invalid size of gesture data %d (expected:%d)\n",
+ bits, (int)(sizeof(struct custom_gesture_data) * 8));
+ return -EINVAL;
+ }
+
+ syna_tcm_get_touch_data(report, report_size, offset, 16, &data);
+ g_pos.x = (unsigned short)data;
+ offset += 16;
+
+ syna_tcm_get_touch_data(report, report_size, offset, 16, &data);
+ g_pos.y = (unsigned short)data;
+ offset += 16;
- report_offset += bits;
+ syna_tcm_get_touch_data(report, report_size, offset, 8, &data);
+ g_pos.major = (unsigned short)data;
+ offset += 8;
+
+ syna_tcm_get_touch_data(report, report_size, offset, 8, &data);
+ g_pos.minor = (unsigned short)data;
+ offset += 8;
+
+ *report_offset += bits;
+
+ LOGI("Gesture data x:%d y:%d major:%d minor:%d\n",
+ g_pos.x, g_pos.y, g_pos.major, g_pos.minor);
+ } else {
+ return -EINVAL;
+ }
return bits;
}
@@ -1118,6 +1163,7 @@ exit:
pm_relax(&tcm->pdev->dev);
}
#endif
+#if defined(POWER_ALIVE_AT_SUSPEND) && !defined(RESET_ON_RESUME)
/**
* syna_dev_enter_normal_sensing()
*
@@ -1154,6 +1200,8 @@ static int syna_dev_enter_normal_sensing(struct syna_tcm *tcm)
return 0;
}
+#endif
+#ifdef POWER_ALIVE_AT_SUSPEND
/**
* syna_dev_enter_lowpwr_sensing()
*
@@ -1191,10 +1239,9 @@ static int syna_dev_enter_lowpwr_sensing(struct syna_tcm *tcm)
}
}
- tcm->pwr_state = LOW_PWR;
-
return 0;
}
+#endif
static int syna_pinctrl_configure(struct syna_tcm *tcm, bool enable)
{
@@ -1242,6 +1289,7 @@ static int syna_dev_resume(struct device *dev)
struct syna_tcm *tcm = dev_get_drvdata(dev);
struct syna_hw_interface *hw_if = tcm->hw_if;
bool irq_enabled = true;
+ unsigned char status;
/* exit directly if device isn't in suspend state */
if (tcm->pwr_state == PWR_ON)
@@ -1252,32 +1300,39 @@ static int syna_dev_resume(struct device *dev)
syna_pinctrl_configure(tcm, true);
#ifdef RESET_ON_RESUME
+ LOGI("Do reset on resume\n");
syna_pal_sleep_ms(RESET_ON_RESUME_DELAY_MS);
if (hw_if->ops_hw_reset) {
hw_if->ops_hw_reset(hw_if);
+ retval = syna_tcm_get_event_data(tcm->tcm_dev,
+ &status, NULL);
+ if ((retval < 0) || (status != REPORT_IDENTIFY)) {
+ LOGE("Fail to complete hw reset\n");
+ goto exit;
+ }
} else {
retval = syna_tcm_reset(tcm->tcm_dev);
if (retval < 0) {
- LOGE("Fail to do reset\n");
+ LOGE("Fail to do sw reset\n");
goto exit;
}
}
#else
+#ifdef POWER_ALIVE_AT_SUSPEND
/* enter normal power mode */
retval = syna_dev_enter_normal_sensing(tcm);
if (retval < 0) {
LOGE("Fail to enter normal power mode\n");
goto exit;
}
-
+#endif
retval = syna_tcm_rezero(tcm->tcm_dev);
if (retval < 0) {
LOGE("Fail to rezero\n");
goto exit;
}
-#endif /* end of RESET_ON_RESUME */
-
+#endif
tcm->pwr_state = PWR_ON;
LOGI("Prepare to set up application firmware\n");
@@ -1292,12 +1347,9 @@ static int syna_dev_resume(struct device *dev)
retval = 0;
LOGI("Device resumed (pwr_state:%d)\n", tcm->pwr_state);
-
exit:
- /* once lpwg is enabled, irq should be enabled already.
- * otherwise, set irq back to active mode.
- */
- irq_enabled = (!tcm->lpwg_enabled);
+ /* set irq back to active mode if not enabled yet */
+ irq_enabled = (!hw_if->bdata_attn.irq_enabled);
/* enable irq */
if (irq_enabled && (hw_if->ops_enable_irq))
@@ -1349,6 +1401,7 @@ static int syna_dev_suspend(struct device *dev)
LOGE("Fail to enter suspended power mode\n");
return retval;
}
+ tcm->pwr_state = LOW_PWR;
#else
tcm->pwr_state = PWR_OFF;
#endif
diff --git a/syna_tcm2.h b/syna_tcm2.h
index 40273a3..a03cb65 100644
--- a/syna_tcm2.h
+++ b/syna_tcm2.h
@@ -54,7 +54,7 @@
#define SYNAPTICS_TCM_DRIVER_ID (1 << 0)
#define SYNAPTICS_TCM_DRIVER_VERSION 1
-#define SYNAPTICS_TCM_DRIVER_SUBVER "2.3"
+#define SYNAPTICS_TCM_DRIVER_SUBVER "2.5"
/**
* @section: Driver Configurations
@@ -101,7 +101,7 @@
* from suspend.
* Set "disable" in default.
*/
-/* #define RESET_ON_RESUME */
+#define RESET_ON_RESUME
/**
* @brief ENABLE_WAKEUP_GESTURE
@@ -257,7 +257,7 @@
/**
* @brief ENABLE_HELPER
- * Open if willing to do additional handling upon helper wokqueue
+ * Open if willing to do additional handling upon helper workqueue
*
* Set "disable" in default
*/
diff --git a/syna_tcm2_sysfs.c b/syna_tcm2_sysfs.c
index b9206af..1028d55 100644
--- a/syna_tcm2_sysfs.c
+++ b/syna_tcm2_sysfs.c
@@ -501,6 +501,16 @@ static ssize_t syna_sysfs_reset_store(struct kobject *kobj,
}
tcm->hw_if->ops_hw_reset(tcm->hw_if);
+
+ /* enable the interrupt to process the identify report
+ * after the hardware reset.
+ */
+ if (!tcm->hw_if->bdata_attn.irq_enabled) {
+ tcm->hw_if->ops_enable_irq(tcm->hw_if, true);
+ /* disable it and back to original status */
+ syna_pal_sleep_ms(100);
+ tcm->hw_if->ops_enable_irq(tcm->hw_if, false);
+ }
} else {
LOGW("Unknown option %d (1:sw / 2:hw)\n", input);
retval = -EINVAL;
diff --git a/syna_tcm2_testing.c b/syna_tcm2_testing.c
index 7c8e057..be8fd36 100644
--- a/syna_tcm2_testing.c
+++ b/syna_tcm2_testing.c
@@ -106,7 +106,7 @@ static bool syna_testing_compare_byte_vector(unsigned char *data,
* syna_testing_compare_frame()
*
* Sample code to compare the test result with limits
- * by a lower-bound frame
+ * being formatted as a frame
*
* @param
* [ in] data: target test data
@@ -195,6 +195,112 @@ end_of_lower_bound_limit:
}
/**
+ * syna_testing_compare_list()
+ *
+ * Sample code to compare the test result with limits
+ * being formatted as a list
+ *
+ * @param
+ * [ in] data: target test data
+ * [ in] data_size: size of test data
+ * [ in] rows: the number of rows
+ * [ in] cols: the number of column
+ * [ in] limits_hi: upper-bound test limit
+ * [ in] limits_lo: lower-bound test limit
+ *
+ * @return
+ * on success, true; otherwise, return false
+ */
+static bool syna_testing_compare_list(unsigned char *data,
+ unsigned int data_size, int rows, int cols,
+ const int *limits_hi, const int *limits_lo)
+{
+ bool result = false;
+ int *data_ptr = NULL;
+ int limit;
+ int i;
+
+ if (!data || (data_size == 0)) {
+ LOGE("Invalid test data\n");
+ return false;
+ }
+
+ if (data_size % (rows + cols) != 0) {
+ LOGE("Size mismatched, data:%d (exppected:%d * N)\n",
+ data_size, (rows + cols));
+ result = false;
+ return false;
+ }
+
+ if (rows > LIMIT_BOUNDARY) {
+ LOGE("Rows mismatched, rows:%d (exppected:%d)\n",
+ rows, LIMIT_BOUNDARY);
+ result = false;
+ return false;
+ }
+
+ if (cols > LIMIT_BOUNDARY) {
+ LOGE("Columns mismatched, cols: %d (exppected:%d)\n",
+ cols, LIMIT_BOUNDARY);
+ result = false;
+ return false;
+ }
+
+ result = true;
+
+ if (!limits_hi)
+ goto end_of_upper_bound_limit;
+
+ data_ptr = (int *)&data[0];
+ for (i = 0; i < cols; i++) {
+ limit = limits_hi[i];
+ if (*data_ptr > limit) {
+ LOGE("Fail on cols-%2d=%5d, limits_hi:%4d\n",
+ i, *data_ptr, limit);
+ result = false;
+ }
+ data_ptr++;
+ }
+ for (i = 0; i < rows; i++) {
+ limit = limits_hi[LIMIT_BOUNDARY + i];
+ if (*data_ptr > limit) {
+ LOGE("Fail on row-%2d=%5d, limits_hi:%4d\n",
+ i, *data_ptr, limit);
+ result = false;
+ }
+ data_ptr++;
+ }
+
+end_of_upper_bound_limit:
+
+ if (!limits_lo)
+ goto end_of_lower_bound_limit;
+
+ data_ptr = (int *)&data[0];
+ for (i = 0; i < cols; i++) {
+ limit = limits_lo[i];
+ if (*data_ptr < limit) {
+ LOGE("Fail on cols-%2d=%5d, limits_lo:%4d\n",
+ i, *data_ptr, limit);
+ result = false;
+ }
+ data_ptr++;
+ }
+ for (i = 0; i < rows; i++) {
+ limit = limits_lo[LIMIT_BOUNDARY + i];
+ if (*data_ptr < limit) {
+ LOGE("Fail on row-%2d=%5d, limits_lo:%4d\n",
+ i, *data_ptr, limit);
+ result = false;
+ }
+ data_ptr++;
+ }
+
+end_of_lower_bound_limit:
+ return result;
+}
+
+/**
* syna_testing_device_id()
*
* Sample code to ensure the device id is expected
@@ -827,6 +933,209 @@ exit:
static struct kobj_attribute kobj_attr_pt11 =
__ATTR(pt11, 0444, syna_testing_pt11_show, NULL);
+/**
+ * syna_testing_pt12()
+ *
+ * Sample code to perform PT12 testing
+ *
+ * @param
+ * [ in] tcm: the driver handle
+ *
+ * @return
+ * on success, 0; otherwise, negative value on error.
+ */
+static int syna_testing_pt12(struct syna_tcm *tcm, struct tcm_buffer *test_data)
+{
+ int retval;
+ bool result = false;
+
+ LOGI("Start testing\n");
+
+ retval = syna_tcm_run_production_test(tcm->tcm_dev,
+ TEST_PID18_HYBRID_ABS_RAW,
+ test_data);
+ if (retval < 0) {
+ LOGE("Fail to run test %d\n", TEST_PID18_HYBRID_ABS_RAW);
+ result = false;
+ goto exit;
+ }
+
+ result = syna_testing_compare_list(test_data->buf,
+ test_data->data_length,
+ tcm->tcm_dev->rows,
+ tcm->tcm_dev->cols,
+ (const int *)&pt12_limits[0],
+ NULL);
+
+exit:
+ LOGI("Result = %s\n", (result)?"pass":"fail");
+
+ return ((result) ? 0 : -1);
+}
+
+/**
+ * syna_testing_pt12_show()
+ *
+ * Attribute to show the result of PT12 test to the console.
+ *
+ * @param
+ * [ in] kobj: an instance of kobj
+ * [ in] attr: an instance of kobj attribute structure
+ * [out] buf: string buffer shown on console
+ *
+ * @return
+ * on success, number of characters being output;
+ * otherwise, negative value on error.
+ */
+static ssize_t syna_testing_pt12_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ int retval, i;
+ unsigned int count = 0;
+ struct syna_tcm *tcm = g_tcm_ptr;
+ struct tcm_buffer test_data;
+ int *data_ptr = NULL;
+
+ if (!tcm->is_connected) {
+ count = snprintf(buf, PAGE_SIZE,
+ "Device is NOT connected\n");
+ goto exit;
+ }
+
+ syna_set_bus_ref(tcm, SYNA_BUS_REF_SYSFS, true);
+
+ syna_tcm_buf_init(&test_data);
+
+ retval = syna_testing_pt12(tcm, &test_data);
+
+ count = snprintf(buf, PAGE_SIZE,
+ "TEST PT$12: %s\n", (retval < 0) ? "fail" : "pass");
+
+ count += scnprintf(buf + count, PAGE_SIZE - count, "%d %d\n",
+ tcm->tcm_dev->cols, tcm->tcm_dev->rows);
+
+ data_ptr = (int *)&(test_data.buf[0]);
+ for (i = 0; i < tcm->tcm_dev->cols; i++) {
+ count += scnprintf(buf + count, PAGE_SIZE - count, "%d ",
+ data_ptr[i]);
+ }
+ count += scnprintf(buf + count, PAGE_SIZE - count, "\n");
+ for (i = 0; i < tcm->tcm_dev->rows; i++) {
+ count += scnprintf(buf + count, PAGE_SIZE - count, "%d ",
+ data_ptr[tcm->tcm_dev->cols + i]);
+ }
+ count += scnprintf(buf + count, PAGE_SIZE - count, "\n");
+
+ syna_tcm_buf_release(&test_data);
+
+ syna_set_bus_ref(tcm, SYNA_BUS_REF_SYSFS, false);
+exit:
+ return count;
+}
+
+static struct kobj_attribute kobj_attr_pt12 =
+ __ATTR(pt12, 0444, syna_testing_pt12_show, NULL);
+
+/**
+ * syna_testing_pt16()
+ *
+ * Sample code to perform PT16 testing
+ *
+ * @param
+ * [ in] tcm: the driver handle
+ *
+ * @return
+ * on success, 0; otherwise, negative value on error.
+ */
+static int syna_testing_pt16(struct syna_tcm *tcm, struct tcm_buffer *test_data)
+{
+ int retval;
+ bool result = false;
+
+ LOGI("Start testing\n");
+
+ retval = syna_tcm_run_production_test(tcm->tcm_dev,
+ TEST_PID22_TRANS_CAP_RAW,
+ test_data);
+ if (retval < 0) {
+ LOGE("Fail to run test %d\n", TEST_PID22_TRANS_CAP_RAW);
+ result = false;
+ goto exit;
+ }
+
+ result = syna_testing_compare_frame(test_data->buf,
+ test_data->data_length,
+ tcm->tcm_dev->rows,
+ tcm->tcm_dev->cols,
+ (const short *)&pt16_hi_limits[0],
+ (const short *)&pt16_lo_limits[0]);
+
+exit:
+ LOGI("Result = %s\n", (result)?"pass":"fail");
+
+ return ((result) ? 0 : -1);
+}
+
+/**
+ * syna_testing_pt16_show()
+ *
+ * Attribute to show the result of PT11 test to the console.
+ *
+ * @param
+ * [ in] kobj: an instance of kobj
+ * [ in] attr: an instance of kobj attribute structure
+ * [out] buf: string buffer shown on console
+ *
+ * @return
+ * on success, number of characters being output;
+ * otherwise, negative value on error.
+ */
+static ssize_t syna_testing_pt16_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ int retval, i, j;
+ short *data_ptr = NULL;
+ unsigned int count = 0;
+ struct syna_tcm *tcm = g_tcm_ptr;
+ struct tcm_buffer test_data;
+
+ if (!tcm->is_connected) {
+ count = snprintf(buf, PAGE_SIZE,
+ "Device is NOT connected\n");
+ goto exit;
+ }
+
+ syna_set_bus_ref(tcm, SYNA_BUS_REF_SYSFS, true);
+
+ syna_tcm_buf_init(&test_data);
+
+ retval = syna_testing_pt16(tcm, &test_data);
+
+ count = snprintf(buf, PAGE_SIZE,
+ "TEST PT$16: %s\n", (retval < 0) ? "fail" : "pass");
+
+ count += scnprintf(buf + count, PAGE_SIZE - count, "%d %d\n",
+ tcm->tcm_dev->cols, tcm->tcm_dev->rows);
+
+ data_ptr = (short *)&(test_data.buf[0]);
+ for (i = 0; i < tcm->tcm_dev->rows; i++) {
+ for (j = 0; j < tcm->tcm_dev->cols; j++) {
+ count += scnprintf(buf + count, PAGE_SIZE - count, "%d ",
+ data_ptr[i * tcm->tcm_dev->cols + j]);
+ }
+ count += scnprintf(buf + count, PAGE_SIZE - count, "\n");
+ }
+
+ syna_tcm_buf_release(&test_data);
+
+ syna_set_bus_ref(tcm, SYNA_BUS_REF_SYSFS, false);
+exit:
+ return count;
+}
+
+static struct kobj_attribute kobj_attr_pt16 =
+ __ATTR(pt16, 0444, syna_testing_pt16_show, NULL);
+
/*
* declaration of sysfs attributes
*/
@@ -837,6 +1146,8 @@ static struct attribute *attrs[] = {
&kobj_attr_pt0a.attr,
&kobj_attr_pt10.attr,
&kobj_attr_pt11.attr,
+ &kobj_attr_pt12.attr,
+ &kobj_attr_pt16.attr,
NULL,
};
diff --git a/syna_tcm2_testing_limits.h b/syna_tcm2_testing_limits.h
index c8ef469..7fce00f 100644
--- a/syna_tcm2_testing_limits.h
+++ b/syna_tcm2_testing_limits.h
@@ -413,4 +413,104 @@ static const short pt11_lo_limits[LIMIT_BOUNDARY * LIMIT_BOUNDARY] = {
/* 39 */ 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90,
};
+/**
+ * @section test limit for PT12 testing
+ */
+static const int pt12_limits[LIMIT_BOUNDARY + LIMIT_BOUNDARY] = {
+/* 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 */
+/* 00 */ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+/* 01 */ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+};
+
+/**
+ * @section test limit for PT16 testing
+ */
+static const short pt16_hi_limits[LIMIT_BOUNDARY * LIMIT_BOUNDARY] = {
+/* 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 */
+/* 00 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000,
+/* 01 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000,
+/* 02 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000,
+/* 03 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000,
+/* 04 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000,
+/* 05 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000,
+/* 06 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000,
+/* 07 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000,
+/* 08 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000,
+/* 09 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000,
+/* 10 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000,
+/* 11 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000,
+/* 12 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000,
+/* 13 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000,
+/* 14 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000,
+/* 15 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000,
+/* 16 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000,
+/* 17 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000,
+/* 18 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000,
+/* 19 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000,
+/* 20 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000,
+/* 21 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000,
+/* 22 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000,
+/* 23 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000,
+/* 24 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000,
+/* 25 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000,
+/* 26 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000,
+/* 27 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000,
+/* 28 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000,
+/* 29 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000,
+/* 30 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000,
+/* 31 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000,
+/* 32 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000,
+/* 33 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000,
+/* 34 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000,
+/* 35 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000,
+/* 36 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000,
+/* 37 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000,
+/* 38 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000,
+/* 39 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000,
+};
+
+static const short pt16_lo_limits[LIMIT_BOUNDARY * LIMIT_BOUNDARY] = {
+/* 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 */
+/* 00 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300,
+/* 01 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300,
+/* 02 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300,
+/* 03 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300,
+/* 04 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300,
+/* 05 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300,
+/* 06 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300,
+/* 07 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300,
+/* 08 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300,
+/* 09 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300,
+/* 10 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300,
+/* 11 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300,
+/* 12 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300,
+/* 13 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300,
+/* 14 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300,
+/* 15 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300,
+/* 16 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300,
+/* 17 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300,
+/* 18 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300,
+/* 19 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300,
+/* 20 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300,
+/* 21 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300,
+/* 22 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300,
+/* 23 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300,
+/* 24 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300,
+/* 25 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300,
+/* 26 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300,
+/* 27 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300,
+/* 28 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300,
+/* 29 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300,
+/* 30 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300,
+/* 31 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300,
+/* 32 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300,
+/* 33 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300,
+/* 34 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300,
+/* 35 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300,
+/* 36 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300,
+/* 37 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300,
+/* 38 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300,
+/* 39 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300,
+};
+
#endif /* end of _SYNAPTICS_TCM2_TESTING_LIMITS_H_ */
diff --git a/tcm/synaptics_touchcom_core_dev.h b/tcm/synaptics_touchcom_core_dev.h
index 1b0eb2c..1728830 100644
--- a/tcm/synaptics_touchcom_core_dev.h
+++ b/tcm/synaptics_touchcom_core_dev.h
@@ -44,7 +44,7 @@
#include "syna_tcm2_platform.h"
-#define SYNA_TCM_CORE_LIB_VERSION 0x0115
+#define SYNA_TCM_CORE_LIB_VERSION 0x0118
/**
@@ -335,6 +335,7 @@ enum tcm_test_code {
TEST_PID01_TRX_TRX_SHORTS = 0x01,
TEST_PID02_TRX_SENSOR_OPENS = 0x02,
TEST_PID03_TRX_GROUND_SHORTS = 0x03,
+ TEST_PID04_GPIO_SHORTS = 0x04,
TEST_PID05_FULL_RAW_CAP = 0x05,
TEST_PID06_EE_SHORT = 0x06,
TEST_PID07_DYNAMIC_RANGE = 0x07,
@@ -348,7 +349,9 @@ enum tcm_test_code {
TEST_PID16_SENSOR_SPEED = 0x10,
TEST_PID17_ADC_RANGE = 0x11,
TEST_PID18_HYBRID_ABS_RAW = 0x12,
+ TEST_PID22_TRANS_CAP_RAW = 0x16,
TEST_PID29_HYBRID_ABS_NOISE = 0x1D,
+ TEST_PID30_BSC_CALIB = 0x1E,
TEST_PID_MAX,
};
diff --git a/tcm/synaptics_touchcom_core_v1.c b/tcm/synaptics_touchcom_core_v1.c
index 75d4c4a..17a7ca4 100644
--- a/tcm/synaptics_touchcom_core_v1.c
+++ b/tcm/synaptics_touchcom_core_v1.c
@@ -190,13 +190,15 @@ static void syna_tcm_v1_dispatch_report(struct tcm_dev *tcm_dev)
syna_pal_completion_complete(cmd_completion);
goto exit;
default:
- LOGN("Device has been reset\n");
+ LOGN("Get unexpected 0x%02X report at command 0x%02X\n",
+ REPORT_IDENTIFY, tcm_msg->command);
ATOMIC_SET(tcm_msg->command_status,
CMD_STATE_ERROR);
syna_pal_completion_complete(cmd_completion);
goto exit;
}
} else {
+ LOGN("Device has been reset\n");
/* invoke callback to handle unexpected reset if doesn't
* result from command
*/
diff --git a/tcm/synaptics_touchcom_func_reflash.c b/tcm/synaptics_touchcom_func_reflash.c
index dff17cc..5115b73 100644
--- a/tcm/synaptics_touchcom_func_reflash.c
+++ b/tcm/synaptics_touchcom_func_reflash.c
@@ -1978,6 +1978,7 @@ int syna_tcm_do_fw_update(struct tcm_dev *tcm_dev,
int retval;
enum update_area type = UPDATE_NONE;
struct tcm_reflash_data_blob reflash_data;
+ int app_status;
if (!tcm_dev) {
LOGE("Invalid tcm device handle\n");
@@ -2008,6 +2009,17 @@ int syna_tcm_do_fw_update(struct tcm_dev *tcm_dev,
ATOMIC_SET(tcm_dev->firmware_flashing, 1);
+ app_status = syna_pal_le2_to_uint(tcm_dev->app_info.status);
+
+ /* to forcedly update the firmware and config
+ * - flag of 'force_reflash' has been set
+ * - device stays in bootloader
+ * - app firmware doesn't run properly
+ */
+ force_reflash = force_reflash ||
+ (IS_BOOTLOADER_MODE(tcm_dev->dev_mode)) ||
+ (IS_APP_FW_MODE(tcm_dev->dev_mode) && (app_status != APP_STATUS_OK));
+
if (force_reflash) {
type = UPDATE_FIRMWARE_CONFIG;
goto reflash;
diff --git a/tcm/synaptics_touchcom_func_romboot.c b/tcm/synaptics_touchcom_func_romboot.c
index 9ad30ad..782bb0f 100644
--- a/tcm/synaptics_touchcom_func_romboot.c
+++ b/tcm/synaptics_touchcom_func_romboot.c
@@ -1189,15 +1189,17 @@ int syna_tcm_romboot_do_ihex_update(struct tcm_dev *tcm_dev,
return _EINVAL;
}
- romboot_data = syna_pal_mem_alloc(1, sizeof(*romboot_data));
+ if (flash_size == 0)
+ flash_size = ihex_size + 4096;
+
+ romboot_data = syna_pal_mem_alloc(1,
+ sizeof(struct tcm_romboot_data_blob));
if (!romboot_data) {
- LOGE("Fail to allocate buffer for romboot_data\n");
+ LOGE("Fail to allocate romboot data blob\n");
+
return _ENOMEM;
}
- if (flash_size == 0)
- flash_size = ihex_size + 4096;
-
romboot_data->bdata = ihex;
romboot_data->bdata_size = ihex_size;
syna_pal_mem_set(&romboot_data->ihex_info, 0x00,
@@ -1210,6 +1212,7 @@ int syna_tcm_romboot_do_ihex_update(struct tcm_dev *tcm_dev,
if (!ihex_info->bin) {
LOGE("Fail to allocate buffer for ihex data\n");
syna_pal_mem_free((void *)romboot_data);
+
return _ENOMEM;
}
@@ -1358,9 +1361,12 @@ int syna_tcm_romboot_do_multichip_reflash(struct tcm_dev *tcm_dev,
struct block_data *block;
struct app_config_header *header;
unsigned int image_fw_id;
+ unsigned char *image_config_id;
+ unsigned char *device_config_id;
unsigned int erase_delay_ms = (wait_delay_ms >> 16) & 0xFFFF;
unsigned int wr_delay_ms = wait_delay_ms & 0xFFFF;
bool has_tool_boot_cfg = false;
+ bool reflash_required = false;
if (!tcm_dev) {
LOGE("Invalid tcm device handle\n");
@@ -1372,16 +1378,15 @@ int syna_tcm_romboot_do_multichip_reflash(struct tcm_dev *tcm_dev,
return _EINVAL;
}
- LOGN("Prepare to do reflash\n");
-
- romboot_data = syna_pal_mem_alloc(1, sizeof(*romboot_data));
+ romboot_data = syna_pal_mem_alloc(1,
+ sizeof(struct tcm_romboot_data_blob));
if (!romboot_data) {
- LOGE("Fail to allocate buffer for romboot_data\n");
+ LOGE("Fail to allocate romboot data blob\n");
+
return _ENOMEM;
}
- syna_pal_mem_set(romboot_data, 0x00,
- sizeof(struct tcm_romboot_data_blob));
+ LOGN("Prepare to do reflash\n");
syna_tcm_buf_init(&romboot_data->out);
@@ -1410,7 +1415,30 @@ int syna_tcm_romboot_do_multichip_reflash(struct tcm_dev *tcm_dev,
LOGN("Device firmware ID: %d, image build id: %d\n",
tcm_dev->packrat_number, image_fw_id);
- if ((image_fw_id <= tcm_dev->packrat_number) && !force_reflash) {
+ if (image_fw_id != tcm_dev->packrat_number) {
+ LOGN("Image build ID and device fw ID mismatched\n");
+ reflash_required = true;
+ }
+
+ image_config_id = header->customer_config_id;
+ device_config_id = tcm_dev->app_info.customer_config_id;
+
+ for (idx = 0; idx < MAX_SIZE_CONFIG_ID; idx++) {
+ if (image_config_id[idx] != device_config_id[idx]) {
+ LOGN("Different Config ID\n");
+ reflash_required = true;
+ }
+ }
+ /* to start the process of firmware update
+ * - fw ID or config ID is mismatched
+ * - device stays in rom-bootloader
+ * - flag of 'force_reflash' has been set
+ */
+ reflash_required = reflash_required ||
+ (IS_ROM_BOOTLOADER_MODE(tcm_dev->dev_mode)) ||
+ force_reflash;
+
+ if (!reflash_required) {
LOGN("No need to do reflash\n");
retval = 0;
goto exit;
@@ -1534,7 +1562,7 @@ exit:
syna_tcm_buf_release(&romboot_data->out);
- syna_pal_mem_free((void *)romboot_data);
+ syna_pal_mem_free(romboot_data);
return retval;
}
diff --git a/tcm/synaptics_touchcom_func_touch.c b/tcm/synaptics_touchcom_func_touch.c
index 8639fbc..d4fd617 100644
--- a/tcm/synaptics_touchcom_func_touch.c
+++ b/tcm/synaptics_touchcom_func_touch.c
@@ -178,7 +178,7 @@ static int syna_tcm_get_gesture_data(const unsigned char *report,
syna_pal_le2_to_uint(gesture_data->tap_y));
break;
default:
- LOGW("Unknown gesture_id:%d\n", gesture_id);
+ LOGD("Unknown gesture_id:%d\n", gesture_id);
break;
}
@@ -437,10 +437,9 @@ int syna_tcm_parse_touch_report(struct tcm_dev *tcm_dev,
touch_data->num_of_active_objects = data;
offset += bits;
if (touch_data->num_of_active_objects == 0) {
- if (end_of_foreach == 0) {
- LOGE("Invalid end_foreach\n");
+ if (end_of_foreach == 0)
return 0;
- }
+
idx = end_of_foreach;
}
break;