input: touchscreen: synaptics_3200: Update Synaptics 3200 driver
* HTC kernel version: m7-kk-3.4.10-17db3b4
Change-Id: Icfc4997d7d6f6257c8f947f2d50eb455481f8832
diff --git a/drivers/input/touchscreen/rmi_dev.c b/drivers/input/touchscreen/rmi_dev.c
index 78aface..212d014 100644
--- a/drivers/input/touchscreen/rmi_dev.c
+++ b/drivers/input/touchscreen/rmi_dev.c
@@ -122,6 +122,17 @@
return ret_value;
}
+/*
+ * rmi_char_dev_write: - use to write data into RMI stream
+ *
+ * @filep : file structure for write
+ * @buf: user-level buffer pointer contains data to be written
+ * @count: number of byte be be written
+ * @f_pos: offset (starting register address)
+ *
+ * @return number of bytes written from user buffer (buf) if succeeds
+ * negative number if error occurs.
+ */
static ssize_t rmi_char_dev_write(struct file *filp, const char __user *buf,
size_t count, loff_t *f_pos)
{
diff --git a/drivers/input/touchscreen/synaptics_3200.c b/drivers/input/touchscreen/synaptics_3200.c
index 3b92511..eb22f5d 100644
--- a/drivers/input/touchscreen/synaptics_3200.c
+++ b/drivers/input/touchscreen/synaptics_3200.c
@@ -27,15 +27,25 @@
#include <linux/slab.h>
#include <linux/rmi.h>
#include <mach/board.h>
+#include <mach/board_htc.h>
#include <mach/msm_hsusb.h>
#include <asm/gpio.h>
#include <linux/input/mt.h>
#include <linux/pl_sensor.h>
+#include <linux/async.h>
+#include <linux/firmware.h>
+#include <linux/kthread.h>
+#include <linux/wait.h>
#define SYN_I2C_RETRY_TIMES 10
+#define SYN_UPDATE_RETRY_TIMES 5
#define SHIFT_BITS 10
#define SYN_WIRELESS_DEBUG
+#define SYN_FW_NAME "tp_SYN.img"
+#define SYN_FW_TIMEOUT (30000)
+static DEFINE_MUTEX(syn_fw_mutex);
+
struct synaptics_ts_data {
uint16_t addr;
struct i2c_client *client;
@@ -54,9 +64,11 @@
uint8_t finger_support;
uint16_t finger_pressed;
int (*power)(int on);
+ int (*lpm_power)(int on);
struct early_suspend early_suspend;
int pre_finger_data[11][4];
uint32_t debug_log_level;
+ uint32_t enable_noise_log;
uint32_t raw_base;
uint32_t raw_ref;
uint64_t timestamp;
@@ -70,6 +82,7 @@
uint16_t tap_suppression;
uint8_t ambiguous_state;
uint8_t diag_command;
+ uint8_t disable_CBC;
uint8_t cable_support;
uint8_t cable_config;
uint8_t key_number;
@@ -109,6 +122,7 @@
uint8_t multitouch_calibration;
uint32_t width_factor;
uint32_t height_factor;
+ uint8_t finger_func_idx;
uint8_t psensor_detection;
uint8_t psensor_resume_enable;
uint8_t psensor_phone_enable;
@@ -117,6 +131,11 @@
struct work_struct psensor_work;
struct workqueue_struct *syn_psensor_wq;
struct synaptics_virtual_key *button;
+ wait_queue_head_t syn_fw_wait;
+ atomic_t syn_fw_condition;
+ uint8_t block_touch_time_near;
+ uint8_t block_touch_time_far;
+ uint8_t block_touch_event;
};
#ifdef CONFIG_HAS_EARLYSUSPEND
@@ -139,6 +158,41 @@
extern unsigned int get_tamper_sf(void);
+static DEFINE_MUTEX(syn_block_mutex);
+static void syn_block_touch(struct synaptics_ts_data *ts, int enable)
+{
+ mutex_lock(&syn_block_mutex);
+ ts->block_touch_event = enable;
+ mutex_unlock(&syn_block_mutex);
+ printk(KERN_INFO "[TP] Block Touch Event:%d\n", enable);
+}
+
+static void syn_block_touch_work_func(struct work_struct *dummy)
+{
+ struct synaptics_ts_data *ts = gl_ts;
+ syn_block_touch(ts, 0);
+}
+static DECLARE_DELAYED_WORK(syn_block_touch_work, syn_block_touch_work_func);
+
+static void syn_handle_block_touch(struct synaptics_ts_data *ts, int enable)
+{
+ int ret;
+ if (ts->block_touch_event) {
+ ret = __cancel_delayed_work(&syn_block_touch_work);
+ syn_block_touch(ts, 0);
+ }
+ if (enable) {
+ if (ts->block_touch_time_near && enable == 1) {
+ ret = schedule_delayed_work(&syn_block_touch_work, HZ*ts->block_touch_time_near/1000);
+ syn_block_touch(ts, 1);
+ }
+ if (ts->block_touch_time_far && enable == 2) {
+ ret = schedule_delayed_work(&syn_block_touch_work, HZ*ts->block_touch_time_far/1000);
+ syn_block_touch(ts, 1);
+ }
+ }
+}
+
static void syn_page_select(struct i2c_client *client, uint8_t page)
{
struct synaptics_ts_data *ts = i2c_get_clientdata(client);
@@ -367,33 +421,13 @@
else
return -1;
}
-static int get_int_mask(uint8_t number, uint8_t offset)
-{
- uint8_t i, mask = 0;
- for (i = 0; i < number; i++)
- mask |= BIT(i);
- return mask << offset;
-}
-static uint32_t syn_crc(uint16_t *data, uint16_t len)
-{
- uint32_t sum1, sum2;
- sum1 = sum2 = 0xFFFF;
- while (len--) {
- sum1 += *data++;
- sum2 += sum1;
- sum1 = (sum1 & 0xFFFF) + (sum1 >> 16);
- sum2 = (sum2 & 0xFFFF) + (sum2 >> 16);
- }
- return sum1 | (sum2 << 16);
-}
-
-static int wait_flash_interrupt(struct synaptics_ts_data *ts, int attr)
+static int wait_flash_interrupt(struct synaptics_ts_data *ts, int attr, int fw)
{
uint8_t data = 0;
int i, ret;
- for (i = 0; i < 5; i++) {
+ for (i = 0; i < 5000; i++) {
#ifdef SYN_FLASH_PROGRAMMING_LOG
printk(KERN_INFO "[TP] ATT: %d\n", gpio_get_value(attr));
#endif
@@ -409,26 +443,38 @@
break;
}
}
- hr_msleep(20);
+ if (fw)
+ mdelay(2);
+ else
+ hr_msleep(2);
}
- if (i == 5 && syn_panel_version == 0) {
+ if (i == 5000 && syn_panel_version == 0) {
ret = i2c_syn_read(ts->client, get_address_base(ts, 0x01, DATA_BASE) + 1, &data, 1);
if (ret < 0)
return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "r:2", __func__);
- } else if (i == 5) {
+ } else if (i == 5000) {
printk(KERN_INFO "[TP] wait_flash_interrupt: interrupt over time!\n");
return SYN_PROCESS_ERR;
}
- ret = i2c_syn_read(ts->client,
- get_address_base(ts, 0x34, DATA_BASE) + 18, &data, 1);
+ if (ts->package_id < 3400)
+ ret = i2c_syn_read(ts->client,
+ get_address_base(ts, 0x34, DATA_BASE) + 0x12, &data, 1);
+ else
+ ret = i2c_syn_read(ts->client,
+ get_address_base(ts, 0x34, DATA_BASE) + 0x3, &data, 1);
if (ret < 0)
return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "r:3", __func__);
- if (data != 0x80) {
- printk(KERN_INFO "[TP] wait_flash_interrupt: block config fail!\n");
+ if (!(data & 0x80)) {
+ printk(KERN_INFO "[TP] Not in program enable mode, F34_data = %x\n", data);
+ ret = i2c_syn_read(ts->client,
+ get_address_base(ts, 0x01, DATA_BASE), &data, 1);
+ printk(KERN_INFO "[TP] Not in program enable mode, 01_data = %x\n", data);
return SYN_PROCESS_ERR;
+ } else if (data != 0x80) {
+ printk(KERN_INFO "[TP] Not in program enable mode, data = %x\n", data);
}
return 0;
}
@@ -436,124 +482,45 @@
static int enable_flash_programming(struct synaptics_ts_data *ts, int attr)
{
int ret;
- uint8_t data[2];
+ uint8_t data[2] = {0};
+ if (attr) {
+ if (!gpio_get_value(attr)) {
+ ret = i2c_syn_read(ts->client,
+ get_address_base(ts, 0x01, DATA_BASE) + 1, data, 1);
+ if (ret < 0)
+ return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "r:1", __func__);
+ printk(KERN_INFO "[TP] %s: clear gpio_irq before enter bootloader mode, data = %x\n", __func__, data[0]);
+ }
+ }
ret = i2c_syn_read(ts->client,
get_address_base(ts, 0x34, QUERY_BASE), data, 2);
if (ret < 0)
return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "r:1", __func__);
-
- ret = i2c_syn_write(ts->client,
- get_address_base(ts, 0x34, DATA_BASE) + 2, data, 2);
- if (ret < 0)
- return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:2", __func__);
-
- ret = i2c_syn_write_byte_data(ts->client,
- get_address_base(ts, 0x34, DATA_BASE) + 18, 0x0F);
- if (ret < 0)
- return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:3", __func__);
-
- ret = wait_flash_interrupt(ts, attr);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-static int crc_comparison(struct synaptics_ts_data *ts, uint32_t config_crc, int attr)
-{
- int ret;
- uint8_t data[17];
- uint32_t flash_crc;
-#ifdef SYN_FLASH_PROGRAMMING_LOG
- uint8_t i, j;
-
- for (i = 0; i < 0x20; i++) {
- data[0] = i;
- data[1] = 0x00;
-#else
- data[0] = 0x1F;
- data[1] = 0x00;
-#endif
+ if (ts->package_id < 3400)
ret = i2c_syn_write(ts->client,
- get_address_base(ts, 0x34, DATA_BASE), data, 2);
- if (ret < 0)
- return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:1", __func__);
-
- ret = i2c_syn_write_byte_data(ts->client,
- get_address_base(ts, 0x34, DATA_BASE) + 18, 0x05);
- if (ret < 0)
- return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:2", __func__);
-
- ret = wait_flash_interrupt(ts, attr);
- if (ret < 0)
- return ret;
-
- ret = i2c_syn_read(ts->client,
- get_address_base(ts, 0x34, DATA_BASE) + 2, data, 17);
- if (ret < 0)
- return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "r:3", __func__);
-
- memcpy(&flash_crc, &data[12], 4);
-
-#ifdef SYN_FLASH_PROGRAMMING_LOG
- printk(KERN_INFO "[TP] config_crc = %X, flash_crc = %X\n", config_crc, flash_crc);
- for (j = 0; j < 0x11; j++)
- printk(KERN_INFO " %d:%X ", j, data[j]);
- printk(KERN_INFO "\n");
- }
-#endif
-
- if (flash_crc == config_crc)
- return 0;
+ get_address_base(ts, 0x34, DATA_BASE) + 2, data, 2);
else
- return 1;
-}
-
-static int program_config(struct synaptics_ts_data *ts, uint8_t *config, int attr)
-{
- int ret;
- uint8_t data[19];
- uint16_t i;
-
- ret = i2c_syn_read(ts->client,
- get_address_base(ts, 0x34, QUERY_BASE), data, 2);
-
- if (ret < 0)
- return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "r:1", __func__);
-
- ret = i2c_syn_write(ts->client,
- get_address_base(ts, 0x34, DATA_BASE) + 2, data, 2);
+ ret = i2c_syn_write(ts->client,
+ get_address_base(ts, 0x34, DATA_BASE) + 1, data, 2);
if (ret < 0)
return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:2", __func__);
-
- ret = i2c_syn_write_byte_data(ts->client,
- get_address_base(ts, 0x34, DATA_BASE) + 18, 0x07);
+ if (ts->package_id < 3400)
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, 0x34, DATA_BASE) + 18, 0x0F);
+ else
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, 0x34, DATA_BASE) + 2, 0x0F);
if (ret < 0)
return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:3", __func__);
- ret = wait_flash_interrupt(ts, attr);
+ ret = wait_flash_interrupt(ts, attr, 0);
if (ret < 0)
return ret;
- for (i = 0; i < 0x20; i++) {
- data[0] = i & 0xFF;
- data[1] = (i & 0xFF00) >> 8;
- memcpy(&data[2], &config[16 * i], 16);
- data[18] = 0x06;
- ret = i2c_syn_write(ts->client,
- get_address_base(ts, 0x34, DATA_BASE), data, 19);
- if (ret < 0)
- return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:4", __func__);
-
- ret = wait_flash_interrupt(ts, attr);
- if (ret < 0)
- return ret;
- }
-
return 0;
}
@@ -588,6 +555,319 @@
}
}
+
+static int program_fw_img(struct synaptics_ts_data *ts,
+ const uint8_t *imgbuf, const uint16_t filelength)
+{
+ uint8_t data[20] = {0};
+ uint16_t blocksize, fwcnt, cfgcnt ,i;
+ int ret;
+
+ if (syn_pdt_scan(ts, SYN_BL_PAGE) < 0) {
+ printk(KERN_ERR "[TP] TOUCH_ERR:%s: PDT scan fail\n", __func__);
+ return -1;
+ }
+
+ i2c_syn_read(ts->client, get_address_base(ts, 0x34, QUERY_BASE), data, 2);
+
+
+ if (ts->package_id < 3400)
+ i2c_syn_write(ts->client, get_address_base(ts, 0x34, DATA_BASE) + 0x2, data, 2);
+ else
+ i2c_syn_write(ts->client, get_address_base(ts, 0x34, DATA_BASE) + 0x1, data, 2);
+
+
+ printk(KERN_INFO "[TP][FW] Erase firmware and config\n");
+ data[0] = 0x03;
+ if (ts->package_id < 3400)
+ i2c_syn_write(ts->client, get_address_base(ts, 0x34, DATA_BASE) + 0x12, data, 1);
+ else
+ i2c_syn_write(ts->client, get_address_base(ts, 0x34, DATA_BASE) + 0x2, data, 1);
+ ret = wait_flash_interrupt(ts, ts->gpio_irq, 1);
+ if (ret < 0)
+ return ret;
+
+
+ memset(data, 0x0, sizeof(data));
+ if (ts->package_id < 3400)
+ i2c_syn_read(ts->client, get_address_base(ts, 0x34, QUERY_BASE) + 0x3, data, 6);
+ else
+ i2c_syn_read(ts->client, get_address_base(ts, 0x34, QUERY_BASE) + 0x2, data, 6);
+ blocksize = data[0] | data[1] << 8;
+ fwcnt = data[2] | data[3] << 8;
+ cfgcnt = data[4] | data[5] << 8;
+#ifdef SYN_FLASH_PROGRAMMING_LOG
+ printk(KERN_INFO "[TP][FW]Block size: %x, FW Block count: %x, Configure count: %x\n",
+ blocksize, fwcnt, cfgcnt);
+#endif
+
+
+ printk(KERN_INFO "[TP][FW] Program firmware\n");
+ for (i = 0; i < fwcnt; i++)
+ {
+ data[0] = i & 0xFF;
+ data[1] = (i & 0xFF00) >> 8;
+ memcpy(&data[2], &imgbuf[0x100 + (i * blocksize)], blocksize);
+ data[2 + blocksize] = 0x02;
+
+ i2c_syn_write(ts->client, get_address_base(ts, 0x34, DATA_BASE), data, 3 + blocksize);
+
+
+ ret = wait_flash_interrupt(ts, ts->gpio_irq, 1);
+ if (ret < 0)
+ return ret;
+ }
+
+ printk(KERN_INFO "[TP][FW] Program config\n");
+ for (i = 0; i < cfgcnt; i++) {
+ data[0] = i & 0xFF;
+ data[1] = (i & 0xFF00) >> 8;
+ memcpy(&data[2],
+ &imgbuf[0x100 + (fwcnt* blocksize) + (i * blocksize)], blocksize);
+ data[2 + blocksize] = 0x06;
+
+ i2c_syn_write(ts->client, get_address_base(ts, 0x34, DATA_BASE), data, 3 + blocksize);
+
+
+ ret = wait_flash_interrupt(ts, ts->gpio_irq, 1);
+ if (ret < 0)
+ return ret;
+ }
+
+
+ printk(KERN_INFO "[TP][FW] Disable flash programming\n");
+ disable_flash_programming(ts, 1);
+ return 0;
+}
+
+static int syn_firmware_update(struct synaptics_ts_data *ts)
+{
+ int ret = 0, i = 0;
+ uint prnum = 0;
+ uint8_t start_addr = 0;
+ u8 *pos, *pos_end;
+ char prstr[10] = {0};
+ const struct firmware *fw;
+
+ ret = request_firmware(&fw, SYN_FW_NAME, &ts->client->dev);
+ if (fw == NULL) {
+ printk(KERN_INFO"[TP][FW] No firmware file, ignored firmware update\n");
+ goto SYN_FW_REQUEST_FAILUE;
+ }
+ else if (ret) {
+ printk(KERN_INFO"[TP][FW] Request_firmware failed, ret = %d\n", ret);
+ goto SYN_FW_REQUEST_FAILUE;
+ }
+ if (fw->data[0] == 'T' && fw->data[1] == 'P') {
+ pos = strchr(fw->data, 'R');
+
+ pos_end = strchr(fw->data, '\n');
+ start_addr = pos_end - fw->data + 1;
+ memcpy(prstr, &fw->data[(pos - fw->data + 1)], 7);
+ ret = strict_strtoul(prstr, 10, (unsigned long*)&prnum);
+ if (ret < 0) {
+ printk(KERN_INFO "[TP][FW] TP tag parse failed %s, %d\n", prstr, prnum);
+ goto SYN_FW_CHECK_FAILURE;
+ }
+
+ printk(KERN_INFO "[TP][FW] size=%d, pr=%u\n",
+ (fw->size-(pos_end - fw->data + 1)), prnum);
+
+ if (prnum != ts->packrat_number) {
+ printk(KERN_INFO "[TP][FW] PR number is not the same, firmware update...\n");
+
+ mutex_lock(&syn_fw_mutex);
+ for (i = 0; i < 5; i++) {
+ if (!enable_flash_programming(ts, ts->gpio_irq)) {
+ printk(KERN_INFO "[TP][FW] Enable flash ok\n");
+ break;
+ }
+ hr_msleep(20);
+ }
+ if (i == 5) {
+ printk(KERN_ERR "[TP][FW] TOUCH_ERR: syn_eanbl_flash retry 5 time Faile\n");
+ ret = -1;
+ goto SYN_FW_FAILUE;
+ }
+
+ if (!program_fw_img(ts, &fw->data[start_addr],
+ fw->size - start_addr )) {
+ printk(KERN_INFO "[TP][FW] update successfully\n");
+ release_firmware(fw);
+ } else {
+ printk(KERN_INFO "[TP][FW] update failed\n");
+ ret = -2;
+ goto SYN_FW_FAILUE;
+ }
+ mutex_unlock(&syn_fw_mutex);
+ } else {
+ printk(KERN_INFO "[TP][FW] PR number is the same. Ignored\n");
+ ret = 1;
+ goto SYN_FW_PRCHECK_NOT_ALLOW;
+ }
+ } else {
+ printk(KERN_INFO "[TP][FW]Miss TP firmware tag. Ignored\n");
+ ret = 2;
+ goto SYN_FW_CHECK_FAILURE;
+ }
+
+ return 0;
+
+SYN_FW_FAILUE:
+SYN_FW_PRCHECK_NOT_ALLOW:
+SYN_FW_CHECK_FAILURE:
+SYN_FW_REQUEST_FAILUE:
+ release_firmware(fw);
+
+ return ret;
+}
+
+static int syn_fw_update_init(void *arg)
+{
+ int ret;
+ struct synaptics_ts_data *ts = (struct synaptics_ts_data *)arg;
+ printk(KERN_INFO "[TP][FW] %s\n", __func__);
+ ret = syn_firmware_update(ts);
+ if (ret)
+ printk(KERN_INFO "[TP][FW] Bypassed firmware update, ret = %d\n", ret);
+ atomic_set(&ts->syn_fw_condition, 1);
+ wake_up(&ts->syn_fw_wait);
+
+ return ret;
+}
+
+static int get_int_mask(uint8_t number, uint8_t offset)
+{
+ uint8_t i, mask = 0;
+ for (i = 0; i < number; i++)
+ mask |= BIT(i);
+ return mask << offset;
+}
+
+static uint32_t syn_crc(uint16_t *data, uint16_t len)
+{
+ uint32_t sum1, sum2;
+ sum1 = sum2 = 0xFFFF;
+ while (len--) {
+ sum1 += *data++;
+ sum2 += sum1;
+ sum1 = (sum1 & 0xFFFF) + (sum1 >> 16);
+ sum2 = (sum2 & 0xFFFF) + (sum2 >> 16);
+ }
+ return sum1 | (sum2 << 16);
+}
+
+static int crc_comparison(struct synaptics_ts_data *ts, uint32_t config_crc, int attr)
+{
+ int ret;
+ uint8_t data[17];
+ uint32_t flash_crc;
+#ifdef SYN_FLASH_PROGRAMMING_LOG
+ uint8_t i, j;
+
+ for (i = 0; i < 0x20; i++) {
+ data[0] = i;
+ data[1] = 0x00;
+#else
+ data[0] = 0x1F;
+ data[1] = 0x00;
+#endif
+ ret = i2c_syn_write(ts->client,
+ get_address_base(ts, 0x34, DATA_BASE), data, 2);
+ if (ret < 0)
+ return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:1", __func__);
+
+ if (ts->package_id < 3400)
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, 0x34, DATA_BASE) + 18, 0x05);
+ else
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, 0x34, DATA_BASE) + 2, 0x05);
+ if (ret < 0)
+ return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:2", __func__);
+
+ ret = wait_flash_interrupt(ts, attr, 0);
+ if (ret < 0)
+ return ret;
+
+ if (ts->package_id < 3400)
+ ret = i2c_syn_read(ts->client,
+ get_address_base(ts, 0x34, DATA_BASE) + 2, data, 17);
+ else
+ ret = i2c_syn_read(ts->client,
+ get_address_base(ts, 0x34, DATA_BASE) + 1, data, 17);
+ if (ret < 0)
+ return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "r:3", __func__);
+
+ memcpy(&flash_crc, &data[12], 4);
+
+#ifdef SYN_FLASH_PROGRAMMING_LOG
+ printk(KERN_INFO "[TP] config_crc = %X, flash_crc = %X\n", config_crc, flash_crc);
+ for (j = 0; j < 0x11; j++)
+ printk(KERN_INFO " %d:%X ", j, data[j]);
+ printk(KERN_INFO "\n");
+ }
+#endif
+
+ if (flash_crc == config_crc)
+ return 0;
+ else
+ return 1;
+}
+
+static int program_config(struct synaptics_ts_data *ts, uint8_t *config, int attr)
+{
+ int ret;
+ uint8_t data[19];
+ uint16_t i;
+
+ ret = i2c_syn_read(ts->client,
+ get_address_base(ts, 0x34, QUERY_BASE), data, 2);
+
+ if (ret < 0)
+ return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "r:1", __func__);
+
+ if (ts->package_id < 3400)
+ ret = i2c_syn_write(ts->client,
+ get_address_base(ts, 0x34, DATA_BASE) + 2, data, 2);
+ else
+ ret = i2c_syn_write(ts->client,
+ get_address_base(ts, 0x34, DATA_BASE) + 1, data, 2);
+ if (ret < 0)
+ return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:2", __func__);
+
+
+ if (ts->package_id < 3400)
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, 0x34, DATA_BASE) + 18, 0x07);
+ else
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, 0x34, DATA_BASE) + 2, 0x07);
+ if (ret < 0)
+ return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:3", __func__);
+
+ ret = wait_flash_interrupt(ts, attr, 0);
+ if (ret < 0)
+ return ret;
+
+ for (i = 0; i < 0x20; i++) {
+ data[0] = i & 0xFF;
+ data[1] = (i & 0xFF00) >> 8;
+ memcpy(&data[2], &config[16 * i], 16);
+ data[18] = 0x06;
+ ret = i2c_syn_write(ts->client,
+ get_address_base(ts, 0x34, DATA_BASE), data, 19);
+ if (ret < 0)
+ return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:4", __func__);
+
+ ret = wait_flash_interrupt(ts, attr, 0);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
static int syn_config_update(struct synaptics_ts_data *ts, int attr)
{
uint8_t retry;
@@ -648,7 +928,7 @@
static int syn_get_tw_vendor(struct synaptics_ts_data *ts, int attr)
{
- uint8_t data[2] = {0};
+ uint8_t data[6] = {0};
int ret;
ret = enable_flash_programming(ts, attr);
@@ -665,20 +945,36 @@
memcpy(&data, &ts->tw_pin_mask, sizeof(ts->tw_pin_mask));
printk(KERN_INFO "[TP] tw mask = %X %X , %X\n", data[0], data[1], ts->tw_pin_mask);
- i2c_syn_write(ts->client,
- get_address_base(ts, 0x34, DATA_BASE) + 2, data, 2);
- i2c_syn_write(ts->client,
- get_address_base(ts, 0x34, DATA_BASE) + 4, data, 2);
- i2c_syn_write_byte_data(ts->client,
- get_address_base(ts, 0x34, DATA_BASE) + 18, 0x08);
+ data[2] = data[0];
+ data[3] = data[1];
+ if (ts->package_id < 3400) {
+ i2c_syn_write(ts->client,
+ get_address_base(ts, 0x34, DATA_BASE) + 2, data, 2);
+ i2c_syn_write(ts->client,
+ get_address_base(ts, 0x34, DATA_BASE) + 4, data, 2);
+ i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, 0x34, DATA_BASE) + 18, 0x08);
+ } else {
+ i2c_syn_write(ts->client,
+ get_address_base(ts, 0x34, DATA_BASE) + 1, data, 4);
+ i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, 0x34, DATA_BASE) + 2, 0x08);
+ }
- if (wait_flash_interrupt(ts, attr) < 0)
+ if (wait_flash_interrupt(ts, attr, 0) < 0)
return disable_flash_programming(ts, -1);
- i2c_syn_read(ts->client,
- get_address_base(ts, 0x34, DATA_BASE) + 6, data, 2);
- ts->tw_vendor = (data[1] << 8) | data[0];
- printk(KERN_INFO "[TP] tw vendor= %x %x\n", data[1], data[0]);
+ if (ts->package_id < 3400) {
+ i2c_syn_read(ts->client,
+ get_address_base(ts, 0x34, DATA_BASE) + 6, data, 2);
+ ts->tw_vendor = (data[1] << 8) | data[0];
+ printk(KERN_INFO "[TP] tw vendor= %x %x\n", data[1], data[0]);
+ } else {
+ i2c_syn_read(ts->client,
+ get_address_base(ts, 0x34, DATA_BASE) + 1, data, 6);
+ ts->tw_vendor = (data[5] << 8) | data[4];
+ printk(KERN_INFO "[TP] tw vendor= %x %x\n", data[5], data[4]);
+ }
return 0;
}
@@ -702,6 +998,7 @@
set_bit(KEY_MENU, ts->input_dev->keybit);
set_bit(KEY_SEARCH, ts->input_dev->keybit);
set_bit(KEY_APP_SWITCH, ts->input_dev->keybit);
+ set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit);
printk(KERN_INFO "[TP] input_set_abs_params: mix_x %d, max_x %d, min_y %d, max_y %d\n",
ts->layout[0], ts->layout[1], ts->layout[2], ts->layout[3]);
@@ -820,7 +1117,6 @@
}
}
}
-
return count;
}
@@ -854,6 +1150,10 @@
if(i!=count-2)
ts->debug_log_level <<= 4;
}
+ if (ts->debug_log_level & BIT(17))
+ ts->enable_noise_log = 1;
+ else
+ ts->enable_noise_log = 0;
return count;
}
@@ -889,7 +1189,7 @@
}
wait_event_interruptible_timeout(syn_data_ready_wq,
- atomic_read(&ts->data_ready), 50);
+ atomic_read(&ts->data_ready), 50);
for (i = 0; i < ts->y_channel; i++) {
for (j = 0; j < ts->x_channel; j++) {
@@ -900,7 +1200,6 @@
}
count += sprintf(buf + count, "\n");
}
-
return count;
}
@@ -920,12 +1219,119 @@
static DEVICE_ATTR(diag, (S_IWUSR|S_IRUGO),
syn_diag_show, syn_diag_store);
+static ssize_t syn_cbc_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct synaptics_ts_data *ts;
+ int ret;
+ uint8_t data = 0, update = 0;
+ ts = gl_ts;
+ if (buf[0] == '0') {
+ if (ts->package_id < 3400) {
+ ret = i2c_syn_read(ts->client,
+ get_address_base(ts, 0x54, CONTROL_BASE) + 0x07, &data, 1);
+ if ((data & 0x10) == 0) {
+ data |= 0x10;
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, 0x54, CONTROL_BASE) + 0x07, data);
+ update = 1;
+ }
+ } else {
+ ret = i2c_syn_read(ts->client,
+ get_address_base(ts, 0x54, CONTROL_BASE) + 0x1E, &data, 1);
+ if ((data & 0x20) == 0) {
+ data |= 0x20;
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, 0x54, CONTROL_BASE) + 0x1E, data);
+ update = 1;
+ }
+ }
+ if (ts->button) {
+ if (ts->package_id < 3400) {
+ ret = i2c_syn_read(ts->client,
+ get_address_base(ts, 0x54, CONTROL_BASE) + 0x56, &data, 1);
+ if ((data & 0x10) == 0) {
+ data |= 0x10;
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, 0x54, CONTROL_BASE) + 0x56, data);
+ update = 1;
+ }
+ } else {
+ ret = i2c_syn_read(ts->client,
+ get_address_base(ts, 0x54, CONTROL_BASE) + 0x19, &data, 1);
+ if ((data & 0x10) == 0) {
+ data |= 0x10;
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, 0x54, CONTROL_BASE) + 0x19, data);
+ update = 1;
+ }
+ }
+ }
+ if (update) {
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, 0x54, COMMAND_BASE), 0x04);
+ }
+ ts->disable_CBC = 0;
+ } else if (buf[0] == '1') {
+ if (ts->package_id < 3400) {
+ ret = i2c_syn_read(ts->client,
+ get_address_base(ts, 0x54, CONTROL_BASE) + 0x07, &data, 1);
+ if (data & 0x10) {
+ data &= 0xEF;
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, 0x54, CONTROL_BASE) + 0x07, data);
+ update = 1;
+ }
+ } else {
+ ret = i2c_syn_read(ts->client,
+ get_address_base(ts, 0x54, CONTROL_BASE) + 0x1E, &data, 1);
+ if (data & 0x20) {
+ data &= 0xDF;
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, 0x54, CONTROL_BASE) + 0x1E, data);
+ update = 1;
+ }
+ }
+ if (ts->button) {
+ if (ts->package_id < 3400) {
+ ret = i2c_syn_read(ts->client,
+ get_address_base(ts, 0x54, CONTROL_BASE) + 0x56, &data, 1);
+ if (data & 0x10) {
+ data &= 0xEF;
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, 0x54, CONTROL_BASE) + 0x56, data);
+ update = 1;
+ }
+ } else {
+ ret = i2c_syn_read(ts->client,
+ get_address_base(ts, 0x54, CONTROL_BASE) + 0x19, &data, 1);
+ if (data & 0x10) {
+ data &= 0xEF;
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, 0x54, CONTROL_BASE) + 0x19, data);
+ update = 1;
+ }
+ }
+ }
+ if (update) {
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, 0x54, COMMAND_BASE), 0x04);
+ }
+ ts->disable_CBC = 1;
+ }
+
+ return count;
+}
+
+static DEVICE_ATTR(disable_cbc, (S_IWUSR|S_IRUGO),
+ NULL, syn_cbc_store);
+
static ssize_t syn_unlock_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct synaptics_ts_data *ts;
int unlock = -1;
- int ret;
+ int ret = 0;
ts = gl_ts;
@@ -935,7 +1341,7 @@
printk(KERN_INFO "[TP] Touch: unlock change to %d\n", unlock);
if (unlock == 2 && ts->first_pressed && ts->pre_finger_data[0][0] < 2) {
- ts->pre_finger_data[0][0] = 2;
+ ts->pre_finger_data[0][0] = 2;
if(ts->psensor_detection) {
if(ts->psensor_resume_enable == 1) {
printk(KERN_INFO "[TP] %s: Disable P-sensor by Touch\n", __func__);
@@ -947,14 +1353,64 @@
}
}
if (ts->packrat_number < SYNAPTICS_FW_NOCAL_PACKRAT) {
+#ifdef SYN_CALIBRATION_CONTROL
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, 0x54, CONTROL_BASE) + 0x10, 0x0);
+ if (ret < 0)
+ return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:1", __func__);
+
+ if (ts->energy_ratio_relaxation) {
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, 0x54, CONTROL_BASE), 0x0);
+ if (ret < 0)
+ return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:2", __func__);
+ }
+
+ if (ts->saturation_bef_unlock) {
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, 0x54, CONTROL_BASE) + 0x02, ts->saturation_aft_unlock & 0xFF);
+ if (ret < 0)
+ return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:3", __func__);
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, 0x54, CONTROL_BASE) + 0x03, (ts->saturation_aft_unlock & 0xFF00) >> 8);
+ if (ret < 0)
+ return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:4", __func__);
+ printk(KERN_INFO "[TP] %s: unlock confirmed. set saturation: %x\n"
+ , __func__, ts->saturation_aft_unlock);
+ }
+
+ if ( ts->PixelTouchThreshold_bef_unlock ) {
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, 0x54, CONTROL_BASE) + 0x04, ts->PixelTouchThreshold_aft_unlock);
+ if (ret < 0)
+ return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "F54_ANALOG_CTRL03 Pixel Touch Threshold", __func__);
+ printk(KERN_INFO "[TP] %s: set F54_ANALOG_CTRL03 Pixel Touch Threshold: %x\n", __func__, ts->PixelTouchThreshold_aft_unlock);
+ }
+
+
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, 0x54, COMMAND_BASE), 0x04);
+ if (ret < 0)
+ return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:5", __func__);
+
+ if (ts->multitouch_calibration) {
+ if (ts->package_id < 3400) {
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, ts->finger_func_idx, COMMAND_BASE), 0x01);
+ if (ret < 0)
+ return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:6", __func__);
+ printk(KERN_INFO "[TP] %s: Touch Calibration Confirmed, rezero\n", __func__);
+ }
+ }
+#endif
if (ts->large_obj_check) {
if (ts->package_id == 2200) {
ret = i2c_syn_write_byte_data(ts->client,
- get_address_base(ts, 0x11, CONTROL_BASE) + 0x26, ts->default_large_obj);
+ get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x26, ts->default_large_obj);
} else {
ret = i2c_syn_write_byte_data(ts->client,
- get_address_base(ts, 0x11, CONTROL_BASE) + 0x29, ts->default_large_obj);
+ get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x29, ts->default_large_obj);
}
if (ret < 0)
return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:7", __func__);
@@ -965,11 +1421,11 @@
if (ts->segmentation_bef_unlock) {
if (ts->package_id == 2200) {
ret = i2c_syn_write_byte_data(ts->client,
- get_address_base(ts, 0x11, CONTROL_BASE) + 0x25, ts->segmentation_aft_unlock);
+ get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x25, ts->segmentation_aft_unlock);
} else {
ret = i2c_syn_write_byte_data(ts->client,
- get_address_base(ts, 0x11, CONTROL_BASE) + 0x22, ts->segmentation_aft_unlock);
+ get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x22, ts->segmentation_aft_unlock);
}
if (ret < 0)
return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:8", __func__);
@@ -980,10 +1436,10 @@
if (ts->threshold_bef_unlock) {
if (ts->package_id == 2200) {
ret = i2c_syn_write_byte_data(ts->client,
- get_address_base(ts, 0x11, CONTROL_BASE) + 0x0A, ts->threshold_aft_unlock);
+ get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x0A, ts->threshold_aft_unlock);
} else {
ret = i2c_syn_write_byte_data(ts->client,
- get_address_base(ts, 0x11, CONTROL_BASE) + 0x0C, ts->threshold_aft_unlock);
+ get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x0C, ts->threshold_aft_unlock);
}
if (ret < 0)
return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:9", __func__);
@@ -1378,7 +1834,8 @@
)
return -ENOMEM;
if (get_address_base(gl_ts, 0x54, FUNCTION))
- if (sysfs_create_file(android_touch_kobj, &dev_attr_diag.attr))
+ if (sysfs_create_file(android_touch_kobj, &dev_attr_diag.attr) ||
+ sysfs_create_file(android_touch_kobj, &dev_attr_disable_cbc.attr))
return -ENOMEM;
#ifdef SYN_WIRELESS_DEBUG
@@ -1387,7 +1844,7 @@
printk(KERN_INFO "[TP]%s: Failed to obtain touchpad IRQ %d. Code: %d.", __func__, ts->gpio_irq, ret);
return ret;
}
- if (ts->gpio_reset) {
+ if (ts->gpio_reset && !ts->i2c_err_handler_en) {
ret = gpio_request(ts->gpio_reset, "synaptics_reset");
if (ret)
printk(KERN_INFO "[TP]%s: Failed to obtain reset pin: %d. Code: %d.", __func__, ts->gpio_reset, ret);
@@ -1444,38 +1901,47 @@
return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:1", __func__);
if (ts->pre_finger_data[0][0] < 2) {
if (ts->large_obj_check) {
- if (ts->package_id == 2200) {
- ret = i2c_syn_write_byte_data(ts->client,
- get_address_base(ts, 0x11, CONTROL_BASE) + 0x26, ts->default_large_obj & 0x7F);
- } else {
- ret = i2c_syn_write_byte_data(ts->client,
- get_address_base(ts, 0x11, CONTROL_BASE) + 0x29, ts->default_large_obj & 0x7F);
+ if (ts->package_id < 3400) {
+ if (ts->package_id == 2200) {
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x26, ts->default_large_obj & 0x7F);
+ } else {
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x29, ts->default_large_obj & 0x7F);
+ }
+ if (ret < 0)
+ return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:2", __func__);
+ printk(KERN_INFO "[TP] %s: set large obj suppression register to: %x\n", __func__, ts->default_large_obj & 0x7F);
}
- if (ret < 0)
- return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:2", __func__);
- printk(KERN_INFO "[TP] %s: set large obj suppression register to: %x\n", __func__, ts->default_large_obj & 0x7F);
}
if (ts->segmentation_bef_unlock) {
- if (ts->package_id == 2200) {
- ret = i2c_syn_write_byte_data(ts->client,
- get_address_base(ts, 0x11, CONTROL_BASE) + 0x25, ts->segmentation_bef_unlock);
- } else {
- ret = i2c_syn_write_byte_data(ts->client,
- get_address_base(ts, 0x11, CONTROL_BASE) + 0x22, ts->segmentation_bef_unlock);
+ if (ts->package_id < 3400) {
+ if (ts->package_id == 2200) {
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x25, ts->segmentation_bef_unlock);
+ } else {
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x22, ts->segmentation_bef_unlock);
+ }
+ if (ret < 0)
+ return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:3", __func__);
+ printk(KERN_INFO "[TP] %s: set segmentation aggressiveness to: %x\n", __func__, ts->segmentation_bef_unlock);
}
- if (ret < 0)
- return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:3", __func__);
- printk(KERN_INFO "[TP] %s: set segmentation aggressiveness to: %x\n", __func__, ts->segmentation_bef_unlock);
}
if (ts->threshold_bef_unlock) {
- if (ts->package_id == 2200) {
- ret = i2c_syn_write_byte_data(ts->client,
- get_address_base(ts, 0x11, CONTROL_BASE) + 0x0A, ts->threshold_bef_unlock);
+ if (ts->package_id < 3400) {
+ if (ts->package_id == 2200) {
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x0A, ts->threshold_bef_unlock);
+ } else {
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x0C, ts->threshold_bef_unlock);
+ }
} else {
ret = i2c_syn_write_byte_data(ts->client,
- get_address_base(ts, 0x11, CONTROL_BASE) + 0x0C, ts->threshold_bef_unlock);
+ get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x01, ts->threshold_bef_unlock);
}
if (ret < 0)
return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:4", __func__);
@@ -1511,25 +1977,62 @@
}
}
+#ifdef SYN_CALIBRATION_CONTROL
+ if (ts->packrat_number < SYNAPTICS_FW_NOCAL_PACKRAT) {
+ if (ts->pre_finger_data[0][0] >= 2 || ts->mfg_flag == 1) {
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, 0x54, CONTROL_BASE) + 0x10, 0x0);
+ if (ret < 0)
+ return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:6", __func__);
+
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, 0x54, COMMAND_BASE), 0x04);
+ if (ret < 0)
+ return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:7", __func__);
+
+ printk(KERN_INFO "[TP] %s: Touch init: set fast relaxation to 0x0\n", __func__);
+ }
+ }
+#endif
+
return ret;
}
static void synaptics_ts_finger_func(struct synaptics_ts_data *ts)
{
int ret;
- uint8_t buf[((ts->finger_support * 21 + 3) / 4)];
+ uint8_t buf[ts->finger_support * 8 ], noise_index[10], noise_state = 0;
+ static int x_pos[10] = {0}, y_pos[10] = {0};
memset(buf, 0x0, sizeof(buf));
- ret = i2c_syn_read(ts->client,
- get_address_base(ts, 0x11, DATA_BASE), buf, sizeof(buf));
+ memset(noise_index, 0x0, sizeof(noise_index));
+ if (ts->package_id < 3400)
+ ret = i2c_syn_read(ts->client,
+ get_address_base(ts, 0x01, DATA_BASE) + 2, buf, sizeof(buf));
+ else {
+ ret = i2c_syn_read(ts->client,
+ get_address_base(ts, ts->finger_func_idx, DATA_BASE), buf, sizeof(buf));
+ ret = i2c_syn_read(ts->client,
+ get_address_base(ts, 0x54, DATA_BASE) + 8, &noise_state, 1);
+ if (noise_state == 2) {
+ ret = i2c_syn_read(ts->client,
+ get_address_base(ts, 0x54, DATA_BASE) + 4, noise_index, sizeof(noise_index));
+ ts->debug_log_level |= BIT(17);
+ } else {
+ if (!ts->enable_noise_log)
+ ts->debug_log_level &= ~BIT(17);
+ }
+ }
if (ret < 0) {
i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "r:1", __func__);
} else {
int finger_data[ts->finger_support][4];
- int base = (ts->finger_support + 3) / 4;
+ int base = 0;
uint8_t i, j;
uint16_t finger_press_changed = 0, finger_release_changed = 0, finger_pressed = 0;
+ if (ts->package_id < 3400)
+ base = (ts->finger_support + 3) / 4;
ts->finger_count = 0;
if (ts->debug_log_level & BIT(0)) {
printk(KERN_INFO "[TP] Touch:");
@@ -1538,7 +2041,12 @@
printk(KERN_INFO "\n");
}
for (i = 0; i < ts->finger_support; i++) {
- uint8_t finger_state = buf[(i / 4)] >> ((i * 2) % 8);
+ uint8_t finger_state;
+ if (ts->package_id < 3400)
+ finger_state = buf[(i / 4)] >> ((i * 2) % 8);
+ else
+ finger_state = buf[i * 8];
+
if (finger_state & 0x03) {
finger_pressed |= BIT(i);
ts->finger_count++;
@@ -1547,6 +2055,7 @@
else if (finger_state == 0x03)
printk(KERN_INFO "[TP] Finger state[%d] = 0x03\n", i);
}
+
#ifdef SYN_FILTER_CONTROL
else if ((ts->grip_suppression | ts->grip_b_suppression) & BIT(i)) {
ts->grip_suppression &= ~BIT(i);
@@ -1565,19 +2074,26 @@
if(ts->debug_log_level & BIT(3)) {
for(i = 0; i < ts->finger_support; i++) {
if (finger_release_changed & BIT(i) ) {
- uint32_t flip_flag = SYNAPTICS_FLIP_X;
- uint8_t pos_mask = 0x0f;
- for (j = 0; j < 2; j++) {
- finger_data[i][j]
- = (buf[base+2] & pos_mask) >> (j * 4) |
- (uint16_t)buf[base + j] << 4;
- if (ts->flags & flip_flag)
- finger_data[i][j] = ts->max[j] - finger_data[i][j];
- flip_flag <<= 1;
- pos_mask <<= 4;
+ if (ts->package_id < 3400) {
+ uint32_t flip_flag = SYNAPTICS_FLIP_X;
+ uint8_t pos_mask = 0x0f;
+ for (j = 0; j < 2; j++) {
+ finger_data[i][j]
+ = (buf[base+2] & pos_mask) >> (j * 4) |
+ (uint16_t)buf[base + j] << 4;
+ if (ts->flags & flip_flag)
+ finger_data[i][j] = ts->max[j] - finger_data[i][j];
+ flip_flag <<= 1;
+ pos_mask <<= 4;
+ }
+ finger_data[i][2] = (buf[base+3] >> 4 & 0x0F) + (buf[base+3] & 0x0F);
+ finger_data[i][3] = buf[base+4];
+ } else {
+ finger_data[i][0] = (buf[base+2] << 8) + buf[base+1];
+ finger_data[i][1] = (buf[base+4] << 8) + buf[base+3];
+ finger_data[i][2] = buf[base+6] + buf[base+7];
+ finger_data[i][3] = buf[base+5];
}
- finger_data[i][2] = (buf[base+3] >> 4 & 0x0F) + (buf[base+3] & 0x0F);
- finger_data[i][3] = buf[base+4];
if (ts->flags & SYNAPTICS_SWAP_XY)
swap(finger_data[i][0], finger_data[i][1]);
@@ -1587,13 +2103,13 @@
if(ts->width_factor && ts->height_factor){
printk(KERN_INFO
"[TP] Screen:F[%02d]:Up, X=%d, Y=%d, W=%d, Z=%d\n",
- i+1, (finger_data[i][0]*ts->width_factor)>>SHIFT_BITS,
- (finger_data[i][1]*ts->height_factor)>>SHIFT_BITS,
+ i+1, (x_pos[i]*ts->width_factor)>>SHIFT_BITS,
+ (y_pos[i]*ts->height_factor)>>SHIFT_BITS,
finger_data[i][2], finger_data[i][3]);
} else {
printk(KERN_INFO
"[TP] Raw:F[%02d]:Up, X=%d, Y=%d, W=%d, Z=%d\n",
- i+1, finger_data[i][0], finger_data[i][1],
+ i+1, x_pos[i], y_pos[i],
finger_data[i][2], finger_data[i][3]);
}
}
@@ -1620,6 +2136,11 @@
input_report_abs(ts->input_dev, ABS_MT_POSITION, 1 << 31);
}
input_mt_sync(ts->input_dev);
+ } else if (ts->htc_event == SYN_AND_REPORT_TYPE_B) {
+ if (ts->support_htc_event) {
+ input_report_abs(ts->input_dev, ABS_MT_AMPLITUDE, 0);
+ input_report_abs(ts->input_dev, ABS_MT_POSITION, 1 << 31);
+ }
}
else if (ts->htc_event == SYN_AND_REPORT_TYPE_HTC) {
input_report_abs(ts->input_dev, ABS_MT_AMPLITUDE, 0);
@@ -1638,22 +2159,32 @@
}
if (ts->pre_finger_data[0][0] < 2 || finger_pressed) {
- base = (ts->finger_support + 3) / 4;
+ if (ts->package_id < 3400)
+ base = (ts->finger_support + 3) / 4;
+ else
+ base = 0;
for (i = 0; i < ts->finger_support; i++) {
uint32_t flip_flag = SYNAPTICS_FLIP_X;
if ((finger_pressed | finger_release_changed) & BIT(i)) {
- uint8_t pos_mask = 0x0f;
- for (j = 0; j < 2; j++) {
- finger_data[i][j]
- = (buf[base+2] & pos_mask) >> (j * 4) |
- (uint16_t)buf[base + j] << 4;
- if (ts->flags & flip_flag)
- finger_data[i][j] = ts->max[j] - finger_data[i][j];
- flip_flag <<= 1;
- pos_mask <<= 4;
+ if (ts->package_id < 3400) {
+ uint8_t pos_mask = 0x0f;
+ for (j = 0; j < 2; j++) {
+ finger_data[i][j]
+ = (buf[base+2] & pos_mask) >> (j * 4) |
+ (uint16_t)buf[base + j] << 4;
+ if (ts->flags & flip_flag)
+ finger_data[i][j] = ts->max[j] - finger_data[i][j];
+ flip_flag <<= 1;
+ pos_mask <<= 4;
+ }
+ finger_data[i][2] = (buf[base+3] >> 4 & 0x0F) + (buf[base+3] & 0x0F);
+ finger_data[i][3] = buf[base+4];
+ } else {
+ finger_data[i][0] = (buf[base+2] << 8) + buf[base+1];
+ finger_data[i][1] = (buf[base+4] << 8) + buf[base+3];
+ finger_data[i][2] = buf[base+6] + buf[base+7];
+ finger_data[i][3] = buf[base+5];
}
- finger_data[i][2] = (buf[base+3] >> 4 & 0x0F) + (buf[base+3] & 0x0F);
- finger_data[i][3] = buf[base+4];
if (ts->flags & SYNAPTICS_SWAP_XY)
swap(finger_data[i][0], finger_data[i][1]);
@@ -1666,7 +2197,7 @@
if (ts->finger_count == 0)
ts->first_pressed = 1;
printk(KERN_INFO "[TP] E%d@%d, %d\n", i + 1,
- finger_data[i][0], finger_data[i][1]);
+ x_pos[i], y_pos[i]);
}
}
#ifdef SYN_FILTER_CONTROL
@@ -1704,7 +2235,7 @@
ts->tap_suppression &= ~BIT(i);
} else {
finger_pressed &= ~BIT(i);
- if (ts->debug_log_level & (BIT(1) | BIT(3)))
+ if (ts->debug_log_level & BIT(1))
printk(KERN_INFO
"[TP] Filtered Finger %d=> X:%d, Y:%d w:%d, z:%d\n",
i + 1, finger_data[i][0], finger_data[i][1],
@@ -1714,57 +2245,60 @@
}
if ((finger_pressed & BIT(i)) == BIT(i)) {
- finger_pressed &= ~BIT(i);
-
- if (ts->htc_event == SYN_AND_REPORT_TYPE_A) {
- if (ts->support_htc_event) {
+ if (ts->block_touch_event == 0) {
+ if (ts->htc_event == SYN_AND_REPORT_TYPE_A) {
+ if (ts->support_htc_event) {
+ input_report_abs(ts->input_dev, ABS_MT_AMPLITUDE,
+ finger_data[i][3] << 16 | finger_data[i][2]);
+ input_report_abs(ts->input_dev, ABS_MT_POSITION,
+ (finger_pressed == 0) << 31 |
+ finger_data[i][0] << 16 | finger_data[i][1]);
+ }
+ input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, i);
+ input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR,
+ finger_data[i][3]);
+ input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR,
+ finger_data[i][2]);
+ input_report_abs(ts->input_dev, ABS_MT_PRESSURE,
+ finger_data[i][2]);
+ input_report_abs(ts->input_dev, ABS_MT_POSITION_X,
+ finger_data[i][0]);
+ input_report_abs(ts->input_dev, ABS_MT_POSITION_Y,
+ finger_data[i][1]);
+ input_mt_sync(ts->input_dev);
+ } else if (ts->htc_event == SYN_AND_REPORT_TYPE_B) {
+ if (ts->support_htc_event) {
+ input_report_abs(ts->input_dev, ABS_MT_AMPLITUDE,
+ finger_data[i][3] << 16 | finger_data[i][2]);
+ input_report_abs(ts->input_dev, ABS_MT_POSITION,
+ (finger_pressed == 0) << 31 |
+ finger_data[i][0] << 16 | finger_data[i][1]);
+ }
+ input_mt_slot(ts->input_dev, i);
+ input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER,
+ 1);
+ input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR,
+ finger_data[i][3]);
+ input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR,
+ finger_data[i][2]);
+ input_report_abs(ts->input_dev, ABS_MT_PRESSURE,
+ finger_data[i][2]);
+ input_report_abs(ts->input_dev, ABS_MT_POSITION_X,
+ finger_data[i][0]);
+ input_report_abs(ts->input_dev, ABS_MT_POSITION_Y,
+ finger_data[i][1]);
+ } else if (ts->htc_event == SYN_AND_REPORT_TYPE_HTC) {
+ input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, i);
input_report_abs(ts->input_dev, ABS_MT_AMPLITUDE,
finger_data[i][3] << 16 | finger_data[i][2]);
input_report_abs(ts->input_dev, ABS_MT_POSITION,
(finger_pressed == 0) << 31 |
finger_data[i][0] << 16 | finger_data[i][1]);
}
- input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, i);
- input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR,
- finger_data[i][3]);
- input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR,
- finger_data[i][2]);
- input_report_abs(ts->input_dev, ABS_MT_PRESSURE,
- finger_data[i][2]);
- input_report_abs(ts->input_dev, ABS_MT_POSITION_X,
- finger_data[i][0]);
- input_report_abs(ts->input_dev, ABS_MT_POSITION_Y,
- finger_data[i][1]);
- input_mt_sync(ts->input_dev);
- } else if (ts->htc_event == SYN_AND_REPORT_TYPE_B) {
- if (ts->support_htc_event) {
- input_report_abs(ts->input_dev, ABS_MT_AMPLITUDE,
- finger_data[i][3] << 16 | finger_data[i][2]);
- input_report_abs(ts->input_dev, ABS_MT_POSITION,
- (finger_pressed == 0) << 31 |
- finger_data[i][0] << 16 | finger_data[i][1]);
- }
- input_mt_slot(ts->input_dev, i);
- input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER,
- 1);
- input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR,
- finger_data[i][3]);
- input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR,
- finger_data[i][2]);
- input_report_abs(ts->input_dev, ABS_MT_PRESSURE,
- finger_data[i][2]);
- input_report_abs(ts->input_dev, ABS_MT_POSITION_X,
- finger_data[i][0]);
- input_report_abs(ts->input_dev, ABS_MT_POSITION_Y,
- finger_data[i][1]);
- } else if (ts->htc_event == SYN_AND_REPORT_TYPE_HTC) {
- input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, i);
- input_report_abs(ts->input_dev, ABS_MT_AMPLITUDE,
- finger_data[i][3] << 16 | finger_data[i][2]);
- input_report_abs(ts->input_dev, ABS_MT_POSITION,
- (finger_pressed == 0) << 31 |
- finger_data[i][0] << 16 | finger_data[i][1]);
}
+ x_pos[i] = finger_data[i][0];
+ y_pos[i] = finger_data[i][1];
+ finger_pressed &= ~BIT(i);
if ((finger_press_changed & BIT(i)) && ts->debug_log_level & BIT(3)) {
if(ts->width_factor && ts->height_factor){
@@ -1779,6 +2313,8 @@
i+1, finger_data[i][0], finger_data[i][1],
finger_data[i][2], finger_data[i][3]);
}
+ if ((ts->block_touch_time_near | ts->block_touch_time_far) && ts->block_touch_event)
+ printk(KERN_INFO "[TP] Block This Event!!\n");
}
if (ts->pre_finger_data[0][0] < 2) {
@@ -1790,6 +2326,20 @@
printk(KERN_INFO "[TP] S%d@%d, %d\n", i + 1,
finger_data[i][0], finger_data[i][1]);
if (ts->packrat_number < SYNAPTICS_FW_NOCAL_PACKRAT) {
+#ifdef SYN_CALIBRATION_CONTROL
+ if (ts->multitouch_calibration) {
+ if (ts->finger_count == ts->finger_support) {
+ if (ts->package_id < 3400) {
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, ts->finger_func_idx, COMMAND_BASE), 0x01);
+ if (ret < 0)
+ i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:Rezero_1", __func__);
+ printk(KERN_INFO "[TP] %s: Touch Calibration Confirmed, rezero\n", __func__);
+ }
+ } else if (!ts->pre_finger_data[0][0] && ts->finger_count > 1)
+ ts->pre_finger_data[0][0] = 1;
+ }
+#endif
}
}
}
@@ -1807,14 +2357,38 @@
if (ts->debug_log_level & BIT(1))
printk(KERN_INFO
- "[TP] Finger %d=> X:%d, Y:%d w:%d, z:%d\n",
+ "[TP] Finger %d=> X:%d, Y:%d W:%d, Z:%d\n",
i + 1, finger_data[i][0], finger_data[i][1],
finger_data[i][2], finger_data[i][3]);
+ if (ts->debug_log_level & BIT(17))
+ printk(KERN_INFO
+ "[TP] Finger %d=> X:%d, Y:%d W:%d, Z:%d, IM:%d, CIDIM:%d, Freq:%d, NS:%d\n",
+ i + 1, finger_data[i][0], finger_data[i][1], finger_data[i][2],
+ finger_data[i][3], noise_index[1] | noise_index[0],
+ noise_index[6] | noise_index[5], noise_index[9], noise_index[4]);
+ }
+ if (ts->packrat_number < SYNAPTICS_FW_NOCAL_PACKRAT) {
+#ifdef SYN_CALIBRATION_CONTROL
+ if (ts->multitouch_calibration) {
+ if ((finger_release_changed & BIT(i)) && ts->pre_finger_data[0][0] == 1) {
+ if (ts->package_id < 3400) {
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, ts->finger_func_idx, COMMAND_BASE), 0x01);
+ if (ret < 0)
+ i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:Rezero_2", __func__);
+ printk(KERN_INFO "[TP] %s: Touch Calibration Confirmed, rezero\n", __func__);
+ }
+ }
+ }
+#endif
}
if (!ts->finger_count)
ts->pre_finger_data[0][0] = 0;
}
- base += 5;
+ if (ts->package_id < 3400)
+ base += 5;
+ else
+ base += 8;
}
#ifdef SYN_FILTER_CONTROL
if (ts->filter_level[0] && ts->grip_suppression) {
@@ -1862,89 +2436,58 @@
static void synaptics_ts_button_func(struct synaptics_ts_data *ts)
{
int ret;
- uint8_t data = 0;
+ uint8_t data = 0, idx = 0;
uint16_t x_position = 0, y_position = 0;
ret = i2c_syn_read(ts->client,
get_address_base(ts, 0x1A, DATA_BASE), &data, 1);
if (data) {
- if (data & 0x01) {
- printk("[TP] back key pressed\n");
- vk_press = 1;
- if (ts->button) {
- if (ts->button[0].index) {
- x_position = (ts->button[0].x_range_min + ts->button[0].x_range_max) / 2;
- y_position = (ts->button[0].y_range_min + ts->button[0].y_range_max) / 2;
- }
+ vk_press = 1;
+ if (ts->button) {
+ idx = (data == 0x01 ? 0:
+ data == 0x02 ? 1:
+ data == 0x04 ? 2:
+ 100);
+
+ if (idx == 100) {
+ vk_press = 0;
+ pr_err("[TP] vk_data:%#x, idx=%d", data, idx);
+ return;
}
- if (ts->htc_event == SYN_AND_REPORT_TYPE_A) {
- input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, 0);
- input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR,
- 100);
- input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR,
- 100);
- input_report_abs(ts->input_dev, ABS_MT_PRESSURE,
- 100);
- input_report_abs(ts->input_dev, ABS_MT_POSITION_X,
- x_position);
- input_report_abs(ts->input_dev, ABS_MT_POSITION_Y,
- y_position);
- input_mt_sync(ts->input_dev);
- } else if (ts->htc_event == SYN_AND_REPORT_TYPE_B) {
- input_mt_slot(ts->input_dev, 0);
- input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER,
- 1);
- input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR,
- 100);
- input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR,
- 100);
- input_report_abs(ts->input_dev, ABS_MT_PRESSURE,
- 100);
- input_report_abs(ts->input_dev, ABS_MT_POSITION_X,
- x_position);
- input_report_abs(ts->input_dev, ABS_MT_POSITION_Y,
- y_position);
- }
+ x_position = (ts->button[idx].x_range_min + ts->button[idx].x_range_max) / 2;
+ y_position = (ts->button[idx].y_range_min + ts->button[idx].y_range_max) / 2;
}
- else if (data & 0x02) {
- printk("[TP] home key pressed\n");
- vk_press = 1;
- if (ts->button) {
- if (ts->button[1].index) {
- x_position = (ts->button[1].x_range_min + ts->button[1].x_range_max) / 2;
- y_position = (ts->button[1].y_range_min + ts->button[1].y_range_max) / 2;
- }
- }
- if (ts->htc_event == SYN_AND_REPORT_TYPE_A) {
- input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, 0);
- input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR,
- 100);
- input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR,
- 100);
- input_report_abs(ts->input_dev, ABS_MT_PRESSURE,
- 100);
- input_report_abs(ts->input_dev, ABS_MT_POSITION_X,
- x_position);
- input_report_abs(ts->input_dev, ABS_MT_POSITION_Y,
- y_position);
- input_mt_sync(ts->input_dev);
- } else if (ts->htc_event == SYN_AND_REPORT_TYPE_B) {
- input_mt_slot(ts->input_dev, 0);
- input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER,
- 1);
- input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR,
- 100);
- input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR,
- 100);
- input_report_abs(ts->input_dev, ABS_MT_PRESSURE,
- 100);
- input_report_abs(ts->input_dev, ABS_MT_POSITION_X,
- x_position);
- input_report_abs(ts->input_dev, ABS_MT_POSITION_Y,
- y_position);
- }
+ data == 0x01 ? pr_info("[TP] back key pressed, vk=%x\n", data) :
+ data == 0x02 ? pr_info("[TP] home key pressed, vk=%x\n", data) :
+ data == 0x04 ? pr_info("[TP] app key pressed , vk=%x\n", data) :
+ pr_info("[TP] vk=%#x\n", data);
+
+ if (ts->support_htc_event) {
+ input_report_abs(ts->input_dev, ABS_MT_AMPLITUDE, 100 << 16 | 100);
+ input_report_abs(ts->input_dev, ABS_MT_POSITION, x_position << 16 | y_position);
}
- }else {
+ switch (ts->htc_event) {
+ case SYN_AND_REPORT_TYPE_A:
+ input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, 0);
+ break;
+ case SYN_AND_REPORT_TYPE_B:
+ input_mt_slot(ts->input_dev, 0);
+ input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 1);
+ break;
+ }
+ input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 100);
+ input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 100);
+ input_report_abs(ts->input_dev, ABS_MT_PRESSURE, 100);
+ input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x_position);
+ input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y_position);
+ switch (ts->htc_event) {
+ case SYN_AND_REPORT_TYPE_A:
+ input_mt_sync(ts->input_dev);
+ break;
+ case SYN_AND_REPORT_TYPE_B:
+ break;
+ }
+ } else {
printk("[TP] virtual key released\n");
vk_press = 0;
if (ts->htc_event == SYN_AND_REPORT_TYPE_A) {
@@ -1955,6 +2498,10 @@
input_mt_sync(ts->input_dev);
}
else if (ts->htc_event == SYN_AND_REPORT_TYPE_B) {
+ if (ts->support_htc_event) {
+ input_report_abs(ts->input_dev, ABS_MT_AMPLITUDE, 0);
+ input_report_abs(ts->input_dev, ABS_MT_POSITION, 1 << 31);
+ }
input_mt_slot(ts->input_dev, 0);
input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 0);
}
@@ -1996,7 +2543,7 @@
if (ret < 0) {
i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "r", __func__);
} else {
- if (buf & get_address_base(ts, 0x11, INTR_SOURCE))
+ if (buf & get_address_base(ts, ts->finger_func_idx, INTR_SOURCE))
synaptics_ts_finger_func(ts);
if (buf & get_address_base(ts, 0x01, INTR_SOURCE))
synaptics_ts_status_func(ts);
@@ -2022,13 +2569,7 @@
if (ret < 0) {
i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "r", __func__);
} else {
- if (buf & get_address_base(ts, 0x1A, INTR_SOURCE)) {
- if (!ts->finger_count)
- synaptics_ts_button_func(ts);
- else
- printk("[TP] Ignore VK interrupt due to 2d points did not leave\n");
- }
- if (buf & get_address_base(ts, 0x11, INTR_SOURCE)) {
+ if (buf & get_address_base(ts, ts->finger_func_idx, INTR_SOURCE)) {
if (!vk_press) {
synaptics_ts_finger_func(ts);
if(ts->debug_log_level & BIT(2)) {
@@ -2039,6 +2580,12 @@
}
}
}
+ if (buf & get_address_base(ts, 0x1A, INTR_SOURCE)) {
+ if (!ts->finger_count)
+ synaptics_ts_button_func(ts);
+ else
+ printk("[TP] Ignore VK interrupt due to 2d points did not leave\n");
+ }
if (buf & get_address_base(ts, 0x01, INTR_SOURCE))
synaptics_ts_status_func(ts);
if (buf & get_address_base(ts, 0x54, INTR_SOURCE))
@@ -2065,7 +2612,7 @@
printk(KERN_INFO "[TP] Touch: cable change to %d\n", connect_status);
- if (connect_status)
+ if ((connect_status > 0) || (connect_status == CONNECT_TYPE_UNKNOWN))
connect_status = 1;
ret = i2c_syn_read(ts->client, get_address_base(ts, 0x01, CONTROL_BASE), &data, 1);
if (ret < 0) {
@@ -2106,12 +2653,14 @@
ts->psensor_status, status);
if(ts->psensor_detection) {
- if(status == 3 && ts->psensor_resume_enable >= 1) {
- if(!(ts->psensor_status==1 && ts->psensor_resume_enable==1)) {
- ret = i2c_syn_write_byte_data(ts->client, get_address_base(ts, 0x11, COMMAND_BASE), 0x01);
- if (ret < 0)
- i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:Rezero_1", __func__);
- printk(KERN_INFO "[TP] %s: Touch Calibration Confirmed, rezero\n", __func__);
+ if((status & PSENSOR_STATUS) == 3 && ts->psensor_resume_enable >= 1) {
+ if(!((ts->psensor_status & PSENSOR_STATUS)==1 && ts->psensor_resume_enable==1)) {
+ if (ts->package_id < 3400) {
+ ret = i2c_syn_write_byte_data(ts->client, get_address_base(ts, ts->finger_func_idx, COMMAND_BASE), 0x01);
+ if (ret < 0)
+ i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:Rezero_1", __func__);
+ printk(KERN_INFO "[TP] %s: Touch Calibration Confirmed, rezero\n", __func__);
+ }
}
if(ts->psensor_resume_enable == 1)
@@ -2121,8 +2670,17 @@
}
}
- if (ts->psensor_status == 0) {
- if (status == 1)
+ if (ts->block_touch_time_near | ts->block_touch_time_far) {
+ if (status == (PHONE_STATUS | 2)) {
+ syn_handle_block_touch(ts, 1);
+ } else if (status == (PHONE_STATUS | 3) && ts->psensor_status != (PHONE_STATUS | 1)) {
+ syn_handle_block_touch(ts, 2);
+ } else if (status == (PHONE_STATUS | 0))
+ syn_handle_block_touch(ts, 0);
+ }
+
+ if ((ts->psensor_status & PSENSOR_STATUS) == 0) {
+ if ((status & PSENSOR_STATUS) == 1)
ts->psensor_status = status;
else
ts->psensor_status = 0;
@@ -2130,7 +2688,7 @@
ts->psensor_status = status;
if(ts->psensor_detection) {
- if(ts->psensor_status == 0) {
+ if((ts->psensor_status & PSENSOR_STATUS) == 0) {
ts->psensor_resume_enable = 0;
ts->psensor_phone_enable = 0;
}
@@ -2163,6 +2721,11 @@
ts->num_function += num_function[i];
}
+ if (ts->address_table != NULL) {
+ kfree(ts->address_table);
+ ts->address_table = NULL;
+ }
+
if (ts->address_table == NULL) {
ts->address_table = kzalloc(sizeof(struct function_t) * ts->num_function, GFP_KERNEL);
if (ts->address_table == NULL) {
@@ -2207,6 +2770,10 @@
return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "r:1", __func__);
ts->package_id = data[1] << 8 | data[0];
printk(KERN_INFO "[TP] %s: package_id: %d\n", __func__, ts->package_id);
+ if (ts->package_id >= 3400)
+ ts->finger_func_idx = 0x12;
+ else
+ ts->finger_func_idx = 0x11;
ret = i2c_syn_read(ts->client, get_address_base(ts, 0x01, QUERY_BASE) + 18, data, 3);
if (ret < 0)
@@ -2244,22 +2811,33 @@
{
uint8_t data[4] = {0}, i, num_channel, *buf;
int ret = 0;
- ret = i2c_syn_read(ts->client, get_address_base(ts, 0x11, QUERY_BASE) + 1, data, 1);
- if (ret < 0)
- return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "r:1", __func__);
- if ((data[0] & 0x07) == 5)
- ts->finger_support = 10;
- else if ((data[0] & 0x07) < 5)
- ts->finger_support = (data[0] & 0x07) + 1;
- else {
- printk(KERN_INFO "[TP] %s: number of fingers not define: %x\n",
- __func__, data[0] & 0x07);
- return SYN_PROCESS_ERR;
+
+ if (ts->package_id < 3400) {
+ ret = i2c_syn_read(ts->client, get_address_base(ts, ts->finger_func_idx, QUERY_BASE) + 1, data, 1);
+ if (ret < 0)
+ return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "r:1", __func__);
+ if ((data[0] & 0x07) == 5)
+ ts->finger_support = 10;
+ else if ((data[0] & 0x07) < 5)
+ ts->finger_support = (data[0] & 0x07) + 1;
+ else {
+ printk(KERN_INFO "[TP] %s: number of fingers not define: %x\n",
+ __func__, data[0] & 0x07);
+ return SYN_PROCESS_ERR;
+ }
+ } else {
+ ret = i2c_syn_read(ts->client, get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 7, data, 2);
+ if (ret < 0)
+ return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "r:1", __func__);
+ ts->finger_support = data[1];
}
printk(KERN_INFO "[TP] %s: finger_support: %d\n", __func__, ts->finger_support);
- ret = i2c_syn_read(ts->client, get_address_base(ts, 0x11, CONTROL_BASE) + 6, data, 4);
+ if (ts->package_id < 3400)
+ ret = i2c_syn_read(ts->client, get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 6, data, 4);
+ else
+ ret = i2c_syn_read(ts->client, get_address_base(ts, ts->finger_func_idx, CONTROL_BASE), data, 4);
if (ret < 0)
return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "r:2", __func__);
@@ -2321,44 +2899,50 @@
}
if (ts->packrat_number < SYNAPTICS_FW_NOCAL_PACKRAT) {
if (ts->large_obj_check) {
- if (ts->package_id == 2200) {
- ret = i2c_syn_read(ts->client,
- get_address_base(ts, 0x11, CONTROL_BASE) + 0x26, &ts->default_large_obj, 1);
- } else {
- ret = i2c_syn_read(ts->client,
- get_address_base(ts, 0x11, CONTROL_BASE) + 0x29, &ts->default_large_obj, 1);
+ if (ts->package_id < 3400) {
+ if (ts->package_id == 2200) {
+ ret = i2c_syn_read(ts->client,
+ get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x26, &ts->default_large_obj, 1);
+ } else {
+ ret = i2c_syn_read(ts->client,
+ get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x29, &ts->default_large_obj, 1);
+ }
+ if (ret < 0)
+ return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "r:6", __func__);
+ printk(KERN_INFO "[TP] %s: ts->default_large_obj: %x\n", __func__, ts->default_large_obj);
}
- if (ret < 0)
- return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "r:6", __func__);
- printk(KERN_INFO "[TP] %s: ts->default_large_obj: %x\n", __func__, ts->default_large_obj);
}
if (ts->segmentation_bef_unlock) {
- if (ts->package_id == 2200) {
- ret = i2c_syn_read(ts->client,
- get_address_base(ts, 0x11, CONTROL_BASE) + 0x25, &ts->segmentation_aft_unlock, 1);
+ if (ts->package_id < 3400) {
+ if (ts->package_id == 2200) {
+ ret = i2c_syn_read(ts->client,
+ get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x25, &ts->segmentation_aft_unlock, 1);
- } else {
- ret = i2c_syn_read(ts->client,
- get_address_base(ts, 0x11, CONTROL_BASE) + 0x22, &ts->segmentation_aft_unlock, 1);
+ } else {
+ ret = i2c_syn_read(ts->client,
+ get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x22, &ts->segmentation_aft_unlock, 1);
+ }
+ if (ret < 0)
+ return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "r:7", __func__);
+ printk(KERN_INFO "[TP] %s: ts->segmentation_aft_unlock: %x\n", __func__, ts->segmentation_aft_unlock);
}
- if (ret < 0)
- return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "r:7", __func__);
- printk(KERN_INFO "[TP] %s: ts->segmentation_aft_unlock: %x\n", __func__, ts->segmentation_aft_unlock);
}
if (ts->threshold_bef_unlock) {
- if (ts->package_id == 2200) {
- ret = i2c_syn_read(ts->client,
- get_address_base(ts, 0x11, CONTROL_BASE) + 0x0A, &ts->threshold_aft_unlock, 1);
+ if (ts->package_id < 3400) {
+ if (ts->package_id == 2200) {
+ ret = i2c_syn_read(ts->client,
+ get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x0A, &ts->threshold_aft_unlock, 1);
- } else {
- ret = i2c_syn_read(ts->client,
- get_address_base(ts, 0x11, CONTROL_BASE) + 0x0C, &ts->threshold_aft_unlock, 1);
+ } else {
+ ret = i2c_syn_read(ts->client,
+ get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x0C, &ts->threshold_aft_unlock, 1);
+ }
+ if (ret < 0)
+ return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "r:8", __func__);
+ printk(KERN_INFO "[TP] %s: ts->z_threshold_aft_unlock: %x\n", __func__, ts->threshold_aft_unlock);
}
- if (ret < 0)
- return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "r:8", __func__);
- printk(KERN_INFO "[TP] %s: ts->z_threshold_aft_unlock: %x\n", __func__, ts->threshold_aft_unlock);
}
if (ts->saturation_bef_unlock) {
@@ -2382,47 +2966,44 @@
return 0;
}
-static int synaptics_ts_probe(
- struct i2c_client *client, const struct i2c_device_id *id)
+static int syn_probe_init(void *arg)
{
- struct synaptics_ts_data *ts;
- uint8_t i;
- int ret = 0;
+ struct synaptics_ts_data *ts = (struct synaptics_ts_data *)arg;
struct synaptics_i2c_rmi_platform_data *pdata;
- uint8_t data = 0;
+ int ret = 0;
+ uint8_t data = 0, i;
+ uint16_t wait_time = SYN_FW_TIMEOUT;
printk(KERN_INFO "[TP] %s: enter", __func__);
- if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
- printk(KERN_ERR "[TP] TOUCH_ERR: synaptics_ts_probe: need I2C_FUNC_I2C\n");
- ret = -ENODEV;
- goto err_check_functionality_failed;
- }
-
- ts = kzalloc(sizeof(*ts), GFP_KERNEL);
- if (ts == NULL) {
- ret = -ENOMEM;
- goto err_alloc_data_failed;
- }
- ts->client = client;
- i2c_set_clientdata(client, ts);
- pdata = client->dev.platform_data;
+ pdata = ts->client->dev.platform_data;
if (pdata == NULL) {
printk(KERN_INFO "[TP] pdata is NULL\n");
goto err_get_platform_data_fail;
}
- ret = i2c_syn_read(ts->client, 0x00EE, &data, 1);
- if (ret < 0) {
- printk(KERN_INFO "[TP] No Synaptics chip\n");
- goto err_detect_failed;
+ if (board_build_flag() == MFG_BUILD) {
+ wait_time = SYN_FW_TIMEOUT;
+ wait_event_interruptible_timeout(ts->syn_fw_wait, atomic_read(&ts->syn_fw_condition),
+ msecs_to_jiffies(wait_time));
+ }
+ ts->block_touch_event = 0;
+ ts->i2c_err_handler_en = pdata->i2c_err_handler_en;
+ if (ts->i2c_err_handler_en) {
+ ts->gpio_reset = pdata->gpio_reset;
+ ts->use_irq = 1;
+ if (ts->gpio_reset) {
+ ret = gpio_request(ts->gpio_reset, "synaptics_reset");
+ if (ret)
+ printk(KERN_INFO "[TP]%s: Failed to obtain reset pin: %d. Code: %d.", __func__, ts->gpio_reset, ret);
+ }
}
for (i = 0; i < 10; i++) {
- ret = i2c_syn_read(ts->client, SYN_F01DATA_BASEADDR, &data, 1);
+ ret = i2c_syn_read(ts->client, get_address_base(ts, 0x01, DATA_BASE), &data, 1);
if (ret < 0) {
i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "read device status failed!", __func__);
- goto err_detect_failed;
+ goto err_init_failed;
}
if (data & 0x44) {
hr_msleep(20);
@@ -2431,7 +3012,7 @@
#endif
} else if (data & 0x40) {
printk(KERN_ERR "[TP] TOUCH_ERR: synaptics probe: F01_data: %x touch controller stay in bootloader mode!\n", data);
- goto err_detect_failed;
+ goto err_init_failed;
} else
break;
}
@@ -2440,11 +3021,6 @@
uint8_t num = 0;
printk(KERN_INFO "[TP] synaptics probe: touch controller doesn't enter UI mode! F01_data: %x\n", data);
- if (syn_pdt_scan(ts, SYN_BL_PAGE) < 0) {
- printk(KERN_ERR "[TP] TOUCH_ERR: PDT scan fail\n");
- goto err_init_failed;
- }
-
if (pdata) {
while (pdata->default_config != 1) {
if (pdata->default_config == 0) {
@@ -2468,18 +3044,23 @@
"config version and CRC but touch controller always stay in bootloader mode\n");
pdata = pdata - num;
}
-
- if (ts->address_table != NULL) {
- kfree(ts->address_table);
- ts->address_table = NULL;
- }
}
if (syn_pdt_scan(ts, SYN_MAX_PAGE) < 0) {
printk(KERN_ERR "[TP] TOUCH_ERR: PDT scan fail\n");
goto err_init_failed;
}
+ if (board_mfg_mode() == MFG_MODE_OFFMODE_CHARGING) {
+ printk(KERN_INFO "[TP] %s: offmode charging. Set touch chip to sleep mode and skip touch driver probe\n", __func__);
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, 0x01, CONTROL_BASE), 0x01);
+ if (ret < 0)
+ i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "sleep: 0x01", __func__);
+ ret = -ENODEV;
+ goto err_check_offmode_charging;
+ }
+ ts->finger_func_idx = 0x11;
if (syn_get_version(ts) < 0) {
printk(KERN_ERR "[TP] TOUCH_ERR: syn_get_version fail\n");
goto err_init_failed;
@@ -2489,10 +3070,13 @@
while (pdata->packrat_number && pdata->packrat_number > ts->packrat_number) {
pdata++;
}
-
if (pdata->tw_pin_mask) {
ts->tw_pin_mask = pdata->tw_pin_mask;
- ret = syn_get_tw_vendor(ts, pdata->gpio_irq);
+ for (i=0; i<SYN_UPDATE_RETRY_TIMES; i++) {
+ ret = syn_get_tw_vendor(ts, pdata->gpio_irq);
+ if (ret == 0)
+ break;
+ }
if (ret < 0) {
printk(KERN_ERR "[TP] TOUCH_ERR: syn_get_tw_vendor fail\n");
goto err_init_failed;
@@ -2502,7 +3086,6 @@
while (pdata->sensor_id > 0 && pdata->sensor_id != (SENSOR_ID_CHECKING_EN | ts->tw_vendor)) {
pdata++;
}
-
printk(KERN_INFO "[TP] synaptics_ts_probe: pdata->version = %x, pdata->packrat_number = %d,"
" pdata->sensor_id = %x\n", pdata->version, pdata->packrat_number, pdata->sensor_id);
@@ -2512,6 +3095,7 @@
}
ts->power = pdata->power;
+ ts->lpm_power = pdata->lpm_power;
ts->flags = pdata->flags;
ts->htc_event = pdata->report_type;
ts->filter_level = pdata->filter_level;
@@ -2529,6 +3113,8 @@
ts->multitouch_calibration = pdata->multitouch_calibration;
ts->psensor_detection = pdata->psensor_detection;
ts->PixelTouchThreshold_bef_unlock = pdata->PixelTouchThreshold_bef_unlock;
+ ts->block_touch_time_near = pdata->block_touch_time_near;
+ ts->block_touch_time_far = pdata->block_touch_time_far;
#ifdef SYN_CABLE_CONTROL
ts->cable_support = pdata->cable_support;
#endif
@@ -2538,7 +3124,11 @@
}
#ifndef SYN_DISABLE_CONFIG_UPDATE
- ret = syn_config_update(ts, pdata->gpio_irq);
+ for (i=0; i<SYN_UPDATE_RETRY_TIMES; i++) {
+ ret = syn_config_update(ts, pdata->gpio_irq);
+ if (ret >= 0)
+ break;
+ }
if (ret < 0) {
printk(KERN_ERR "[TP] TOUCH_ERR: syn_config_update fail\n");
goto err_init_failed;
@@ -2640,22 +3230,22 @@
gl_ts = ts;
ts->irq_enabled = 0;
- if (client->irq) {
+ if (ts->client->irq) {
ts->use_irq = 1;
- ret = request_threaded_irq(client->irq, NULL, synaptics_irq_thread,
- IRQF_TRIGGER_LOW | IRQF_ONESHOT, client->name, ts);
+ ret = request_threaded_irq(ts->client->irq, NULL, synaptics_irq_thread,
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT, ts->client->name, ts);
if (ret == 0) {
ts->irq_enabled = 1;
ret = i2c_syn_read(ts->client,
get_address_base(ts, 0x01, CONTROL_BASE) + 1, &ts->intr_bit, 1);
if (ret < 0) {
- free_irq(client->irq, ts);
+ free_irq(ts->client->irq, ts);
i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "get interrupt bit failed", __func__);
goto err_get_intr_bit_failed;
}
printk(KERN_INFO "[TP] %s: interrupt enable: %x\n", __func__, ts->intr_bit);
} else {
- dev_err(&client->dev, "[TP] TOUCH_ERR: request_irq failed\n");
+ dev_err(&ts->client->dev, "[TP] TOUCH_ERR: request_irq failed\n");
ts->use_irq = 0;
}
}
@@ -2685,7 +3275,7 @@
usb_register_notifier(&cable_status_handler);
ret = i2c_syn_read(ts->client,
- get_address_base(ts, 0x11, CONTROL_BASE), &ts->cable_config, 1);
+ get_address_base(ts, ts->finger_func_idx, CONTROL_BASE), &ts->cable_config, 1);
if (ret < 0) {
printk(KERN_ERR "[TP] TOUCH_ERR: get cable config failed\n");
goto err_get_cable_config_failed;
@@ -2728,12 +3318,71 @@
if(ts->temp_report_data != NULL)
kfree(ts->temp_report_data);
err_init_failed:
+err_check_offmode_charging:
if(ts->address_table != NULL)
kfree(ts->address_table);
-err_detect_failed:
err_get_platform_data_fail:
kfree(ts);
+ return ret;
+}
+
+static int synaptics_ts_probe(
+ struct i2c_client *client, const struct i2c_device_id *id)
+{
+ struct synaptics_ts_data *ts;
+ struct synaptics_i2c_rmi_platform_data *pdata;
+ int ret = 0;
+ uint8_t data = 0;
+
+ printk(KERN_INFO "[TP] %s: enter", __func__);
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ printk(KERN_ERR "[TP] TOUCH_ERR: synaptics_ts_probe: need I2C_FUNC_I2C\n");
+ ret = -ENODEV;
+ goto err_check_functionality_failed;
+ }
+
+ ts = kzalloc(sizeof(*ts), GFP_KERNEL);
+ if (ts == NULL) {
+ ret = -ENOMEM;
+ goto err_alloc_data_failed;
+ }
+ ts->client = client;
+ i2c_set_clientdata(client, ts);
+ pdata = client->dev.platform_data;
+
+ if (pdata == NULL) {
+ printk(KERN_INFO "[TP] pdata is NULL\n");
+ goto err_get_platform_data_fail;
+ }
+
+ ret = i2c_syn_read(ts->client, 0x00EE, &data, 1);
+ if (ret < 0) {
+ printk(KERN_INFO "[TP] No Synaptics chip\n");
+ goto err_detect_failed;
+ }
+ if (syn_pdt_scan(ts, SYN_BL_PAGE) < 0) {
+ printk(KERN_ERR "[TP] TOUCH_ERR: PDT scan fail\n");
+ goto err_detect_failed;
+ }
+ if (board_build_flag() == MFG_BUILD) {
+ ts->gpio_irq = pdata->gpio_irq;
+ if (syn_get_version(ts) < 0) {
+ printk(KERN_ERR "[TP] TOUCH_ERR: syn_get_version fail\n");
+ goto err_detect_failed;
+ }
+
+ init_waitqueue_head(&ts->syn_fw_wait);
+ atomic_set(&ts->syn_fw_condition, 0);
+ kthread_run(syn_fw_update_init, (void *)ts, "SYN_FW_UPDATE");
+ }
+
+ kthread_run(syn_probe_init, (void *)ts, "SYN_PROBE_INIT");
+ return 0;
+
+err_detect_failed:
+err_get_platform_data_fail:
+ kfree(ts);
err_alloc_data_failed:
err_check_functionality_failed:
return ret;
@@ -2768,7 +3417,8 @@
static int synaptics_ts_suspend(struct i2c_client *client, pm_message_t mesg)
{
- int ret;
+ int ret = 0;
+ uint8_t data = 0, update = 0;
struct synaptics_ts_data *ts = i2c_get_clientdata(client);
printk(KERN_INFO "[TP] %s: enter\n", __func__);
@@ -2788,69 +3438,175 @@
}
}
- if (ts->psensor_status == 0) {
+ if ((ts->psensor_status & PSENSOR_STATUS) == 0) {
ts->pre_finger_data[0][0] = 0;
if (ts->packrat_number < SYNAPTICS_FW_NOCAL_PACKRAT) {
ts->first_pressed = 0;
+#ifdef SYN_CALIBRATION_CONTROL
+ if (ts->mfg_flag != 1) {
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, 0x54, CONTROL_BASE) + 0x10, ts->relaxation);
+ if (ret < 0)
+ i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "fast relaxation", __func__);
+
+ if (ts->energy_ratio_relaxation) {
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, 0x54, CONTROL_BASE), 0x20);
+ if (ret < 0)
+ i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "energy ratio relaxation", __func__);
+ }
+
+ if (ts->saturation_bef_unlock) {
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, 0x54, CONTROL_BASE) + 0x02, ts->saturation_bef_unlock & 0xFF);
+ if (ret < 0)
+ return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "saturation capacitance", __func__);
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, 0x54, CONTROL_BASE) + 0x03, (ts->saturation_bef_unlock & 0xFF00) >> 8);
+ if (ret < 0)
+ return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "saturation capacitance", __func__);
+ printk(KERN_INFO "[TP] touch suspend, saturation capacitance: %x\n", ts->saturation_bef_unlock);
+ }
+
+ if ( ts->PixelTouchThreshold_bef_unlock ) {
+ if (ts->package_id <= 3400 ) {
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, 0x54, CONTROL_BASE) + 0x04, ts->PixelTouchThreshold_bef_unlock );
+ if (ret < 0)
+ return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "F54_ANALOG_CTRL03 Pixel Touch Threshold", __func__);
+ printk(KERN_INFO "[TP] touch suspend, set F54_ANALOG_CTRL03 Pixel Touch Threshold: %x\n", ts->PixelTouchThreshold_bef_unlock);
+ }
+ }
+
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, 0x54, COMMAND_BASE), 0x04);
+ if (ret < 0)
+ i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "force update", __func__);
+ printk(KERN_INFO "[TP] touch suspend, fast relasxation: %x\n", ts->relaxation);
+ }
+#endif
if (ts->large_obj_check) {
- if (ts->package_id == 2200) {
- ret = i2c_syn_write_byte_data(ts->client,
- get_address_base(ts, 0x11, CONTROL_BASE) + 0x26, ts->default_large_obj & 0x7F);
+ if (ts->package_id < 3400) {
+ if (ts->package_id == 2200) {
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x26, ts->default_large_obj & 0x7F);
- } else {
- ret = i2c_syn_write_byte_data(ts->client,
- get_address_base(ts, 0x11, CONTROL_BASE) + 0x29, ts->default_large_obj & 0x7F);
+ } else {
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x29, ts->default_large_obj & 0x7F);
+ }
+ if (ret < 0)
+ i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "large obj suppression", __func__);
+ printk(KERN_INFO "[TP] touch suspend, set large obj suppression: %x\n", ts->default_large_obj & 0x7F);
}
- if (ret < 0)
- i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "large obj suppression", __func__);
- printk(KERN_INFO "[TP] touch suspend, set large obj suppression: %x\n", ts->default_large_obj & 0x7F);
}
if (ts->segmentation_bef_unlock) {
- if (ts->package_id == 2200) {
- ret = i2c_syn_write_byte_data(ts->client,
- get_address_base(ts, 0x11, CONTROL_BASE) + 0x25, ts->segmentation_bef_unlock);
- } else {
- ret = i2c_syn_write_byte_data(ts->client,
- get_address_base(ts, 0x11, CONTROL_BASE) + 0x22, ts->segmentation_bef_unlock);
+ if (ts->package_id < 3400) {
+ if (ts->package_id == 2200) {
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x25, ts->segmentation_bef_unlock);
+ } else {
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x22, ts->segmentation_bef_unlock);
+ }
+ if (ret < 0)
+ i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "segmentation aggressiveness", __func__);
+ printk(KERN_INFO "[TP] touch suspend, set segmentation aggressiveness: %x\n", ts->segmentation_bef_unlock);
}
- if (ret < 0)
- i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "segmentation aggressiveness", __func__);
- printk(KERN_INFO "[TP] touch suspend, set segmentation aggressiveness: %x\n", ts->segmentation_bef_unlock);
}
if (ts->threshold_bef_unlock) {
- if (ts->package_id == 2200) {
- ret = i2c_syn_write_byte_data(ts->client,
- get_address_base(ts, 0x11, CONTROL_BASE) + 0x0A, ts->threshold_bef_unlock);
+ if (ts->package_id < 3400) {
+ if (ts->package_id == 2200) {
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x0A, ts->threshold_bef_unlock);
- } else {
- ret = i2c_syn_write_byte_data(ts->client,
- get_address_base(ts, 0x11, CONTROL_BASE) + 0x0C, ts->threshold_bef_unlock);
+ } else {
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x0C, ts->threshold_bef_unlock);
+ }
+ if (ret < 0)
+ i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "Z Touch threshold", __func__);
+ printk(KERN_INFO "[TP] touch suspend, set Z Touch threshold: %x\n", ts->threshold_bef_unlock);
}
- if (ret < 0)
- i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "Z Touch threshold", __func__);
- printk(KERN_INFO "[TP] touch suspend, set Z Touch threshold: %x\n", ts->threshold_bef_unlock);
}
}
}
else if(ts->psensor_detection)
ts->psensor_phone_enable = 1;
+#ifdef CONFIG_PWRKEY_STATUS_API
if (ts->packrat_number < SYNAPTICS_FW_NOCAL_PACKRAT)
printk(KERN_INFO "[TP][PWR][STATE] get power key state = %d\n", getPowerKeyState());
+#endif
+ if (ts->disable_CBC) {
+ if (ts->package_id < 3400) {
+ ret = i2c_syn_read(ts->client,
+ get_address_base(ts, 0x54, CONTROL_BASE) + 0x07, &data, 1);
+ if ((data & 0x10) == 0) {
+ printk(KERN_INFO "[TP] %s: CBC disabled : %d", __func__, ts->package_id);
+ data |= 0x10;
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, 0x54, CONTROL_BASE) + 0x07, data);
+ update = 1;
+ }
+ } else {
+ ret = i2c_syn_read(ts->client,
+ get_address_base(ts, 0x54, CONTROL_BASE) + 0x1E, &data, 1);
+ if ((data & 0x20) == 0) {
+ printk(KERN_INFO "[TP] %s: CBC disabled : %d", __func__, ts->package_id);
+ data |= 0x20;
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, 0x54, CONTROL_BASE) + 0x1E, data);
+ update = 1;
+ }
+ }
+ if (ts->button) {
+ if (ts->package_id < 3400) {
+ ret = i2c_syn_read(ts->client,
+ get_address_base(ts, 0x54, CONTROL_BASE) + 0x56, &data, 1);
+ if ((data & 0x10) == 0) {
+ printk(KERN_INFO "[TP] %s: 0D CBC disabled : %d", __func__, ts->package_id);
+ data |= 0x10;
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, 0x54, CONTROL_BASE) + 0x56, data);
+ update = 1;
+ }
+ } else {
+ ret = i2c_syn_read(ts->client,
+ get_address_base(ts, 0x54, CONTROL_BASE) + 0x19, &data, 1);
+ if ((data & 0x10) == 0) {
+ printk(KERN_INFO "[TP] %s: 0D CBC disabled : %x", __func__, ts->package_id);
+ data |= 0x10;
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, 0x54, CONTROL_BASE) + 0x19, data);
+ update = 1;
+ }
+ }
+ }
+ if (update) {
+ ret = i2c_syn_write_byte_data(ts->client,
+ get_address_base(ts, 0x54, COMMAND_BASE), 0x04);
+ }
+ ts->disable_CBC = 0;
+ }
if (ts->power)
ts->power(0);
else {
- if (ts->packrat_number >= SYNAPTICS_FW_NOCAL_PACKRAT) {
+ if (ts->packrat_number >= SYNAPTICS_FW_2IN1_PACKRAT) {
ret = i2c_syn_write_byte_data(client,
- get_address_base(ts, 0x01, CONTROL_BASE), 0x01);
+ get_address_base(ts, 0x01, CONTROL_BASE), 0x01);
if (ret < 0)
i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "sleep: 0x01", __func__);
} else {
- if (ts->psensor_status > 0 && getPowerKeyState() == 0) {
+ if ((ts->psensor_status & PSENSOR_STATUS) > 0
+#ifdef CONFIG_PWRKEY_STATUS_API
+ && getPowerKeyState() == 0
+#endif
+ ) {
ret = i2c_syn_write_byte_data(client,
get_address_base(ts, 0x01, CONTROL_BASE), 0x02);
if (ret < 0)
@@ -2862,7 +3618,14 @@
i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "sleep: 0x01", __func__);
}
}
+ if (ts->lpm_power)
+ ts->lpm_power(1);
}
+
+ if ((ts->block_touch_time_near | ts->block_touch_time_far) && ts->block_touch_event) {
+ syn_handle_block_touch(ts, 0);
+ }
+
return 0;
}
@@ -2883,6 +3646,8 @@
}
#endif
} else {
+ if (ts->lpm_power)
+ ts->lpm_power(0);
ret = i2c_syn_write_byte_data(client,
get_address_base(ts, 0x01, CONTROL_BASE), 0x00);
if (ret < 0)
@@ -2902,13 +3667,13 @@
input_report_abs(ts->input_dev, ABS_MT_POSITION, 1 << 31);
}
if (ts->psensor_detection) {
- if(ts->psensor_status == 0) {
+ if((ts->psensor_status & PSENSOR_STATUS) == 0) {
ts->psensor_resume_enable = 1;
printk(KERN_INFO "[TP] %s: Enable P-sensor by Touch\n", __func__);
psensor_enable_by_touch_driver(1);
}
else if(ts->psensor_phone_enable == 0) {
- if(ts->psensor_status != 3)
+ if((ts->psensor_status & PSENSOR_STATUS) != 3)
ts->psensor_resume_enable = 2;
ts->psensor_phone_enable = 1;
@@ -2959,9 +3724,15 @@
},
};
+static void __devinit synaptics_ts_init_async(void *unused, async_cookie_t cookie)
+{
+ i2c_add_driver(&synaptics_ts_driver);
+}
+
static int __devinit synaptics_ts_init(void)
{
- return i2c_add_driver(&synaptics_ts_driver);
+ async_schedule(synaptics_ts_init_async, NULL);
+ return 0;
}
static void __exit synaptics_ts_exit(void)
diff --git a/include/linux/synaptics_i2c_rmi.h b/include/linux/synaptics_i2c_rmi.h
index e66d982..cb54bdb 100644
--- a/include/linux/synaptics_i2c_rmi.h
+++ b/include/linux/synaptics_i2c_rmi.h
@@ -25,6 +25,7 @@
#define SYNAPTICS_3200_NAME "synaptics-3200"
#define SYNAPTICS_FW_3_2_PACKRAT 1115999
#define SYNAPTICS_FW_NOCAL_PACKRAT 1293981
+#define SYNAPTICS_FW_2IN1_PACKRAT 1396865
#define SYN_CONFIG_SIZE 32 * 16
@@ -50,6 +51,8 @@
#define CUS_LIFT_CTRL 3
#define SENSOR_ID_CHECKING_EN 1 << 16
+#define PSENSOR_STATUS 0x03
+#define PHONE_STATUS 0x04
enum {
SYNAPTICS_FLIP_X = 1UL << 0,
@@ -80,6 +83,7 @@
/* If non-zero another array entry follows */
int (*power)(int on); /* Only valid in first array entry */
#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_3K
+ int (*lpm_power)(int on);
struct synaptics_virtual_key *virtual_key;
uint8_t virtual_key_num;
struct kobject *vk_obj;
@@ -146,6 +150,8 @@
uint8_t multitouch_calibration;
uint8_t psensor_detection;
uint8_t PixelTouchThreshold_bef_unlock;
+ uint8_t block_touch_time_near;
+ uint8_t block_touch_time_far;
#endif
};