summaryrefslogtreecommitdiff
path: root/drivers/input/touchscreen/ft6x0x
diff options
context:
space:
mode:
authorSrikant Patnaik2015-01-13 15:08:24 +0530
committerSrikant Patnaik2015-01-13 15:08:24 +0530
commit97327692361306d1e6259021bc425e32832fdb50 (patch)
treefe9088f3248ec61e24f404f21b9793cb644b7f01 /drivers/input/touchscreen/ft6x0x
parent2d05a8f663478a44e088d122e0d62109bbc801d0 (diff)
parenta3a8b90b61e21be3dde9101c4e86c881e0f06210 (diff)
downloadFOSSEE-netbook-kernel-source-97327692361306d1e6259021bc425e32832fdb50.tar.gz
FOSSEE-netbook-kernel-source-97327692361306d1e6259021bc425e32832fdb50.tar.bz2
FOSSEE-netbook-kernel-source-97327692361306d1e6259021bc425e32832fdb50.zip
dirty fix to merging
Diffstat (limited to 'drivers/input/touchscreen/ft6x0x')
-rwxr-xr-xdrivers/input/touchscreen/ft6x0x/Kconfig11
-rwxr-xr-xdrivers/input/touchscreen/ft6x0x/Makefile34
-rwxr-xr-xdrivers/input/touchscreen/ft6x0x/focaltech_ctl.h27
-rwxr-xr-xdrivers/input/touchscreen/ft6x0x/ft5402_config.c2295
-rwxr-xr-xdrivers/input/touchscreen/ft6x0x/ft5402_config.h71
-rwxr-xr-xdrivers/input/touchscreen/ft6x0x/ft5402_ini_config.h411
-rwxr-xr-xdrivers/input/touchscreen/ft6x0x/ft5x0x.c896
-rwxr-xr-xdrivers/input/touchscreen/ft6x0x/ft5x0x.h205
-rwxr-xr-xdrivers/input/touchscreen/ft6x0x/ft5x0x_upg.c506
-rwxr-xr-xdrivers/input/touchscreen/ft6x0x/ft6x06_ex_fun.c1021
-rwxr-xr-xdrivers/input/touchscreen/ft6x0x/ft6x06_ex_fun.h79
-rwxr-xr-xdrivers/input/touchscreen/ft6x0x/ft6x06_ts.c511
-rwxr-xr-xdrivers/input/touchscreen/ft6x0x/ft6x06_ts.h52
-rwxr-xr-xdrivers/input/touchscreen/ft6x0x/ini.c406
-rwxr-xr-xdrivers/input/touchscreen/ft6x0x/ini.h43
15 files changed, 6568 insertions, 0 deletions
diff --git a/drivers/input/touchscreen/ft6x0x/Kconfig b/drivers/input/touchscreen/ft6x0x/Kconfig
new file mode 100755
index 00000000..eb11a558
--- /dev/null
+++ b/drivers/input/touchscreen/ft6x0x/Kconfig
@@ -0,0 +1,11 @@
+config TOUCHSCREEN_FT6X0X
+ tristate "FT5X0X Capacity Touchscreen Device Support"
+ default y
+ depends on ARCH_WMT
+ ---help---
+ Say Y here if you have an WMT based board with touchscreen
+ attached to it.
+ If unsure, say N.
+ To compile this driver as a module, choose M here: the
+ module will be called ft5x0x.
+
diff --git a/drivers/input/touchscreen/ft6x0x/Makefile b/drivers/input/touchscreen/ft6x0x/Makefile
new file mode 100755
index 00000000..859008b8
--- /dev/null
+++ b/drivers/input/touchscreen/ft6x0x/Makefile
@@ -0,0 +1,34 @@
+KERNELDIR=../../../../
+CROSS = arm_1103_le-
+CC= $(CROSS)gcc
+LD= $(CROSS)ld
+STRIP = $(CROSS)strip
+
+DEBUG = n
+
+# Add your debugging flag (or not) to EXTRA_CFLAGS
+ifeq ($(DEBUG),y)
+# DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+DEBFLAGS = -O0 -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+
+else
+ DEBFLAGS = -O2 -Wall
+endif
+
+EXTRA_CFLAGS += $(DEBFLAGS)
+
+
+MY_MODULE_NAME=s_wmt_ts_ft6x0x
+
+#obj-$(CONFIG_TOUCHSCREEN_FT5X0X) := $(MY_MODULE_NAME).o
+obj-m := $(MY_MODULE_NAME).o
+$(MY_MODULE_NAME)-objs := ft5x0x.o ft5x0x_upg.o ft5402_config.o ft6x06_ex_fun.o ini.o ft6x06_ts.o
+
+default:
+ $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) modules
+ $(STRIP) --strip-debug $(MY_MODULE_NAME).ko
+ @rm -rf *.o *~ core .depend .*.cmd *.mod.c .tmp_versions *.order *.symvers
+
+clean:
+ @rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.order *.symvers
+
diff --git a/drivers/input/touchscreen/ft6x0x/focaltech_ctl.h b/drivers/input/touchscreen/ft6x0x/focaltech_ctl.h
new file mode 100755
index 00000000..7c58a15a
--- /dev/null
+++ b/drivers/input/touchscreen/ft6x0x/focaltech_ctl.h
@@ -0,0 +1,27 @@
+#ifndef __FOCALTECH_CTL_H__
+#define __FOCALTECH_CTL_H__
+
+#define FT_RW_IIC_DRV "ft_rw_iic_drv"
+#define FT_RW_IIC_DRV_MAJOR 210 /*预设的ft_rw_iic_drv的主设备号*/
+
+#define FT_I2C_RDWR_MAX_QUEUE 36
+#define FT_I2C_SLAVEADDR 11
+#define FT_I2C_RW 12
+#define FT_RESET_TP 13
+
+typedef struct ft_rw_i2c
+{
+ u8 *buf;
+ u8 flag; /*0-write 1-read*/
+ __u16 length; //the length of data
+}*pft_rw_i2c;
+
+typedef struct ft_rw_i2c_queue
+{
+ struct ft_rw_i2c __user *i2c_queue;
+ int queuenum;
+}*pft_rw_i2c_queue;
+
+int ft_rw_iic_drv_init(struct i2c_client *client);
+void ft_rw_iic_drv_exit(void);
+#endif \ No newline at end of file
diff --git a/drivers/input/touchscreen/ft6x0x/ft5402_config.c b/drivers/input/touchscreen/ft6x0x/ft5402_config.c
new file mode 100755
index 00000000..58683ebd
--- /dev/null
+++ b/drivers/input/touchscreen/ft6x0x/ft5402_config.c
@@ -0,0 +1,2295 @@
+#include "ft5402_config.h"
+//#include <linux/i2c/ft5402_ts.h>
+
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/semaphore.h>
+#include <linux/mutex.h>
+#include <linux/interrupt.h>
+#include <mach/irqs.h>
+
+#include <linux/syscalls.h>
+#include <asm/unistd.h>
+#include <asm/uaccess.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+
+#include "ini.h"
+#include "ft5402_ini_config.h"
+#include "ft5x0x.h"
+
+
+extern int ft5x0x_i2c_txdata(char *txdata, int length);
+
+int ft5402_write_reg(struct i2c_client * client, u8 regaddr, u8 regvalue)
+{
+ unsigned char buf[2] = {0};
+ buf[0] = regaddr;
+ buf[1] = regvalue;
+
+ return ft5x0x_i2c_txdata(buf, 2);
+}
+
+int ft5402_read_reg(struct i2c_client * client, u8 regaddr, u8 * regvalue)
+{
+ int ret;
+
+ struct i2c_msg msgs[] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = 1,
+ .buf = &regaddr,
+ },
+ {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = 1,
+ .buf = regvalue,
+ },
+ };
+ ret = i2c_transfer(client->adapter, msgs, 2);
+ if (ret < 0)
+ pr_err("function:%s. i2c read error: %d\n", __func__, ret);
+ return ret;
+}
+
+/*set tx order
+*@txNO: offset from tx order start
+*@txNO1: tx NO.
+*/
+static int ft5402_set_tx_order(struct i2c_client * client, u8 txNO, u8 txNO1)
+{
+ unsigned char ReCode = 0;
+ if (txNO < FT5402_TX_TEST_MODE_1)
+ ReCode = ft5402_write_reg(client, FT5402_REG_TX_ORDER_START + txNO,
+ txNO1);
+ else {
+ ReCode = ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE_2<<4); /*enter Test mode 2*/
+ if (ReCode >= 0)
+ ReCode = ft5402_write_reg(client,
+ FT5402_REG_TX_ORDER_START + txNO - FT5402_TX_TEST_MODE_1,
+ txNO1);
+ ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE<<4); /*enter Test mode*/
+ }
+ return ReCode;
+}
+
+/*set tx order
+*@txNO: offset from tx order start
+*@pTxNo: return value of tx NO.
+*/
+static int ft5402_get_tx_order(struct i2c_client * client, u8 txNO, u8 *pTxNo)
+{
+ unsigned char ReCode = 0;
+ if (txNO < FT5402_TX_TEST_MODE_1)
+ ReCode = ft5402_read_reg(client, FT5402_REG_TX_ORDER_START + txNO,
+ pTxNo);
+ else {
+ ReCode = ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE_2<<4); /*enter Test mode 2*/
+ if(ReCode >= 0)
+ ReCode = ft5402_read_reg(client,
+ FT5402_REG_TX_ORDER_START + txNO - FT5402_TX_TEST_MODE_1,
+ pTxNo);
+ ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE<<4); /*enter Test mode*/
+ }
+ return ReCode;
+}
+
+/*set tx cap
+*@txNO: tx NO.
+*@cap_value: value of cap
+*/
+static int ft5402_set_tx_cap(struct i2c_client * client, u8 txNO, u8 cap_value)
+{
+ unsigned char ReCode = 0;
+ if (txNO < FT5402_TX_TEST_MODE_1)
+ ReCode = ft5402_write_reg(client, FT5402_REG_TX_CAP_START + txNO,
+ cap_value);
+ else {
+ ReCode = ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE_2<<4); /*enter Test mode 2*/
+ if (ReCode >= 0)
+ ReCode = ft5402_write_reg(client,
+ FT5402_REG_TX_CAP_START + txNO - FT5402_TX_TEST_MODE_1,
+ cap_value);
+ ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE<<4); /*enter Test mode*/
+ }
+ return ReCode;
+}
+
+/*get tx cap*/
+static int ft5402_get_tx_cap(struct i2c_client * client, u8 txNO, u8 *pCap)
+{
+ unsigned char ReCode = 0;
+ if (txNO < FT5402_TX_TEST_MODE_1)
+ ReCode = ft5402_read_reg(client, FT5402_REG_TX_CAP_START + txNO,
+ pCap);
+ else {
+ ReCode = ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE_2<<4); /*enter Test mode 2*/
+ if (ReCode >= 0)
+ ReCode = ft5402_read_reg(client,
+ FT5402_REG_TX_CAP_START + txNO - FT5402_TX_TEST_MODE_1,
+ pCap);
+ ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE<<4); /*enter Test mode*/
+ }
+ return ReCode;
+}
+
+/*set tx offset*/
+static int ft5402_set_tx_offset(struct i2c_client * client, u8 txNO, u8 offset_value)
+{
+ unsigned char temp=0;
+ unsigned char ReCode = 0;
+ if (txNO < FT5402_TX_TEST_MODE_1) {
+ ReCode = ft5402_read_reg(client,
+ FT5402_REG_TX_OFFSET_START + (txNO>>1), &temp);
+ if (ReCode >= 0) {
+ if (txNO%2 == 0)
+ ReCode = ft5402_write_reg(client,
+ FT5402_REG_TX_OFFSET_START + (txNO>>1),
+ (temp&0xf0) + (offset_value&0x0f));
+ else
+ ReCode = ft5402_write_reg(client,
+ FT5402_REG_TX_OFFSET_START + (txNO>>1),
+ (temp&0x0f) + (offset_value<<4));
+ }
+ } else {
+ ReCode = ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE_2<<4); /*enter Test mode 2*/
+ if (ReCode >= 0) {
+ ReCode = ft5402_read_reg(client,
+ FT5402_REG_DEVICE_MODE+((txNO-FT5402_TX_TEST_MODE_1)>>1),
+ &temp); /*enter Test mode 2*/
+ if (ReCode >= 0) {
+ if(txNO%2 == 0)
+ ReCode = ft5402_write_reg(client,
+ FT5402_REG_TX_OFFSET_START+((txNO-FT5402_TX_TEST_MODE_1)>>1),
+ (temp&0xf0)+(offset_value&0x0f));
+ else
+ ReCode = ft5402_write_reg(client,
+ FT5402_REG_TX_OFFSET_START+((txNO-FT5402_TX_TEST_MODE_1)>>1),
+ (temp&0xf0)+(offset_value<<4));
+ }
+ }
+ ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE<<4); /*enter Test mode*/
+ }
+
+ return ReCode;
+}
+
+/*get tx offset*/
+static int ft5402_get_tx_offset(struct i2c_client * client, u8 txNO, u8 *pOffset)
+{
+ unsigned char temp=0;
+ unsigned char ReCode = 0;
+ if (txNO < FT5402_TX_TEST_MODE_1)
+ ReCode = ft5402_read_reg(client,
+ FT5402_REG_TX_OFFSET_START + (txNO>>1), &temp);
+ else {
+ ReCode = ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE_2<<4); /*enter Test mode 2*/
+ if (ReCode >= 0)
+ ReCode = ft5402_read_reg(client,
+ FT5402_REG_TX_OFFSET_START+((txNO-FT5402_TX_TEST_MODE_1)>>1),
+ &temp);
+ ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE<<4); /*enter Test mode*/
+ }
+
+ if (ReCode >= 0)
+ (txNO%2 == 0) ? (*pOffset = (temp&0x0f)) : (*pOffset = (temp>>4));
+ return ReCode;
+}
+
+/*set rx order*/
+static int ft5402_set_rx_order(struct i2c_client * client, u8 rxNO, u8 rxNO1)
+{
+ unsigned char ReCode = 0;
+ ReCode = ft5402_write_reg(client, FT5402_REG_RX_ORDER_START + rxNO,
+ rxNO1);
+ return ReCode;
+}
+
+/*get rx order*/
+static int ft5402_get_rx_order(struct i2c_client * client, u8 rxNO, u8 *prxNO1)
+{
+ unsigned char ReCode = 0;
+ ReCode = ft5402_read_reg(client, FT5402_REG_RX_ORDER_START + rxNO,
+ prxNO1);
+ return ReCode;
+}
+
+/*set rx cap*/
+static int ft5402_set_rx_cap(struct i2c_client * client, u8 rxNO, u8 cap_value)
+{
+ unsigned char ReCode = 0;
+ if (rxNO < FT5402_RX_TEST_MODE_1)
+ ReCode = ft5402_write_reg(client, FT5402_REG_RX_CAP_START + rxNO,
+ cap_value);
+ else {
+ ReCode = ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE_2<<4); /*enter Test mode 2*/
+ if(ReCode >= 0)
+ ReCode = ft5402_write_reg(client,
+ FT5402_REG_RX_CAP_START + rxNO - FT5402_RX_TEST_MODE_1,
+ cap_value);
+ ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE<<4); /*enter Test mode*/
+ }
+
+ return ReCode;
+}
+
+/*get rx cap*/
+static int ft5402_get_rx_cap(struct i2c_client * client, u8 rxNO, u8 *pCap)
+{
+ unsigned char ReCode = 0;
+ if (rxNO < FT5402_RX_TEST_MODE_1)
+ ReCode = ft5402_read_reg(client, FT5402_REG_RX_CAP_START + rxNO,
+ pCap);
+ else {
+ ReCode = ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE_2<<4); /*enter Test mode 2*/
+ if(ReCode >= 0)
+ ReCode = ft5402_read_reg(client,
+ FT5402_REG_RX_CAP_START + rxNO - FT5402_RX_TEST_MODE_1,
+ pCap);
+ ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE<<4); /*enter Test mode*/
+ }
+
+ return ReCode;
+}
+
+/*set rx offset*/
+static int ft5402_set_rx_offset(struct i2c_client * client, u8 rxNO, u8 offset_value)
+{
+ unsigned char temp=0;
+ unsigned char ReCode = 0;
+ if (rxNO < FT5402_RX_TEST_MODE_1) {
+ ReCode = ft5402_read_reg(client,
+ FT5402_REG_RX_OFFSET_START + (rxNO>>1), &temp);
+ if (ReCode >= 0) {
+ if (rxNO%2 == 0)
+ ReCode = ft5402_write_reg(client,
+ FT5402_REG_RX_OFFSET_START + (rxNO>>1),
+ (temp&0xf0) + (offset_value&0x0f));
+ else
+ ReCode = ft5402_write_reg(client,
+ FT5402_REG_RX_OFFSET_START + (rxNO>>1),
+ (temp&0x0f) + (offset_value<<4));
+ }
+ }
+ else {
+ ReCode = ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE_2<<4); /*enter Test mode 2*/
+ if (ReCode >= 0) {
+ ReCode = ft5402_read_reg(client,
+ FT5402_REG_DEVICE_MODE+((rxNO-FT5402_RX_TEST_MODE_1)>>1),
+ &temp); /*enter Test mode 2*/
+ if (ReCode >= 0) {
+ if (rxNO%2 == 0)
+ ReCode = ft5402_write_reg(client,
+ FT5402_REG_RX_OFFSET_START+((rxNO-FT5402_RX_TEST_MODE_1)>>1),
+ (temp&0xf0)+(offset_value&0x0f));
+ else
+ ReCode = ft5402_write_reg(client,
+ FT5402_REG_RX_OFFSET_START+((rxNO-FT5402_RX_TEST_MODE_1)>>1),
+ (temp&0xf0)+(offset_value<<4));
+ }
+ }
+ ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE<<4); /*enter Test mode*/
+ }
+
+ return ReCode;
+}
+
+/*get rx offset*/
+static int ft5402_get_rx_offset(struct i2c_client * client, u8 rxNO, u8 *pOffset)
+{
+ unsigned char temp = 0;
+ unsigned char ReCode = 0;
+ if (rxNO < FT5402_RX_TEST_MODE_1)
+ ReCode = ft5402_read_reg(client,
+ FT5402_REG_RX_OFFSET_START + (rxNO>>1), &temp);
+ else {
+ ReCode = ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE_2<<4); /*enter Test mode 2*/
+ if (ReCode >= 0)
+ ReCode = ft5402_read_reg(client,
+ FT5402_REG_RX_OFFSET_START+((rxNO-FT5402_RX_TEST_MODE_1)>>1),
+ &temp);
+
+ ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE<<4); /*enter Test mode*/
+ }
+
+ if (ReCode >= 0) {
+ if (0 == (rxNO%2))
+ *pOffset = (temp&0x0f);
+ else
+ *pOffset = (temp>>4);
+ }
+
+ return ReCode;
+}
+
+/*set tx num*/
+static int ft5402_set_tx_num(struct i2c_client *client, u8 txnum)
+{
+ return ft5402_write_reg(client, FT5402_REG_TX_NUM, txnum);
+}
+
+/*get tx num*/
+static int ft5402_get_tx_num(struct i2c_client *client, u8 *ptxnum)
+{
+ return ft5402_read_reg(client, FT5402_REG_TX_NUM, ptxnum);
+}
+
+/*set rx num*/
+static int ft5402_set_rx_num(struct i2c_client *client, u8 rxnum)
+{
+ return ft5402_write_reg(client, FT5402_REG_RX_NUM, rxnum);
+}
+
+/*get rx num*/
+static int ft5402_get_rx_num(struct i2c_client *client, u8 *prxnum)
+{
+ return ft5402_read_reg(client, FT5402_REG_RX_NUM, prxnum);
+}
+
+/*set resolution*/
+static int ft5402_set_Resolution(struct i2c_client *client, u16 x, u16 y)
+{
+ unsigned char cRet = 0;
+ cRet &= ft5402_write_reg(client,
+ FT5402_REG_RESOLUTION_X_H, ((unsigned char)(x>>8)));
+ cRet &= ft5402_write_reg(client,
+ FT5402_REG_RESOLUTION_X_L, ((unsigned char)(x&0x00ff)));
+
+ cRet &= ft5402_write_reg(client,
+ FT5402_REG_RESOLUTION_Y_H, ((unsigned char)(y>>8)));
+ cRet &= ft5402_write_reg(client,
+ FT5402_REG_RESOLUTION_Y_L, ((unsigned char)(y&0x00ff)));
+
+ return cRet;
+}
+
+/*get resolution*/
+static int ft5402_get_Resolution(struct i2c_client *client,
+ u16 *px, u16 *py)
+{
+ unsigned char cRet = 0, temp1 = 0, temp2 = 0;
+ cRet &= ft5402_read_reg(client,
+ FT5402_REG_RESOLUTION_X_H, &temp1);
+ cRet &= ft5402_read_reg(client,
+ FT5402_REG_RESOLUTION_X_L, &temp2);
+ (*px) = (((u16)temp1) << 8) | ((u16)temp2);
+
+ cRet &= ft5402_read_reg(client,
+ FT5402_REG_RESOLUTION_Y_H, &temp1);
+ cRet &= ft5402_read_reg(client,
+ FT5402_REG_RESOLUTION_Y_L, &temp2);
+ (*py) = (((u16)temp1) << 8) | ((u16)temp2);
+
+ return cRet;
+}
+
+
+/*set voltage*/
+static int ft5402_set_vol(struct i2c_client *client, u8 Vol)
+{
+ return ft5402_write_reg(client, FT5402_REG_VOLTAGE, Vol);
+}
+
+/*get voltage*/
+static int ft5402_get_vol(struct i2c_client *client, u8 *pVol)
+{
+ return ft5402_read_reg(client, FT5402_REG_VOLTAGE, pVol);
+}
+
+/*set gain*/
+static int ft5402_set_gain(struct i2c_client *client, u8 Gain)
+{
+ return ft5402_write_reg(client, FT5402_REG_GAIN, Gain);
+}
+
+/*get gain*/
+static int ft5402_get_gain(struct i2c_client *client, u8 *pGain)
+{
+ return ft5402_read_reg(client, FT5402_REG_GAIN, pGain);
+}
+
+/*get start rx*/
+static int ft5402_get_start_rx(struct i2c_client *client, u8 *pRx)
+{
+ return ft5402_read_reg(client, FT5402_REG_START_RX, pRx);
+}
+
+
+/*get adc target*/
+static int ft5402_get_adc_target(struct i2c_client *client, u16 *pvalue)
+{
+ int err = 0;
+ u8 tmp1, tmp2;
+ err = ft5402_read_reg(client, FT5402_REG_ADC_TARGET_HIGH,
+ &tmp1);
+ if (err < 0)
+ dev_err(&client->dev, "%s:get adc target high failed\n",
+ __func__);
+ err = ft5402_read_reg(client, FT5402_REG_ADC_TARGET_LOW,
+ &tmp2);
+ if (err < 0)
+ dev_err(&client->dev, "%s:get adc target low failed\n",
+ __func__);
+
+ *pvalue = ((u16)tmp1<<8) + (u16)tmp2;
+ return err;
+}
+
+static int ft5402_set_face_detect_statistics_tx_num(struct i2c_client *client, u8 prevalue)
+{
+ return ft5402_write_reg(client, FT5402_REG_FACE_DETECT_STATISTICS_TX_NUM,
+ prevalue);
+}
+
+static int ft5402_get_face_detect_statistics_tx_num(struct i2c_client *client, u8 *pprevalue)
+{
+ return ft5402_read_reg(client, FT5402_REG_FACE_DETECT_STATISTICS_TX_NUM,
+ pprevalue);
+}
+
+static int ft5402_set_face_detect_pre_value(struct i2c_client *client, u8 prevalue)
+{
+ return ft5402_write_reg(client, FT5402_REG_FACE_DETECT_PRE_VALUE,
+ prevalue);
+}
+
+static int ft5402_get_face_detect_pre_value(struct i2c_client *client, u8 *pprevalue)
+{
+ return ft5402_read_reg(client, FT5402_REG_FACE_DETECT_PRE_VALUE,
+ pprevalue);
+}
+
+static int ft5402_set_face_detect_num(struct i2c_client *client, u8 num)
+{
+ return ft5402_write_reg(client, FT5402_REG_FACE_DETECT_NUM,
+ num);
+}
+
+static int ft5402_get_face_detect_num(struct i2c_client *client, u8 *pnum)
+{
+ return ft5402_read_reg(client, FT5402_REG_FACE_DETECT_NUM,
+ pnum);
+}
+
+
+static int ft5402_set_peak_value_min(struct i2c_client *client, u8 min)
+{
+ return ft5402_write_reg(client, FT5402_REG_BIGAREA_PEAK_VALUE_MIN,
+ min);
+}
+
+static int ft5402_get_peak_value_min(struct i2c_client *client, u8 *pmin)
+{
+ return ft5402_read_reg(client, FT5402_REG_BIGAREA_PEAK_VALUE_MIN,
+ pmin);
+}
+
+static int ft5402_set_diff_value_over_num(struct i2c_client *client, u8 num)
+{
+ return ft5402_write_reg(client, FT5402_REG_BIGAREA_DIFF_VALUE_OVER_NUM,
+ num);
+}
+static int ft5402_get_diff_value_over_num(struct i2c_client *client, u8 *pnum)
+{
+ return ft5402_read_reg(client, FT5402_REG_BIGAREA_DIFF_VALUE_OVER_NUM,
+ pnum);
+}
+
+
+static int ft5402_set_customer_id(struct i2c_client *client, u8 num)
+{
+ return ft5402_write_reg(client, FT5402_REG_CUSTOMER_ID,
+ num);
+}
+static int ft5402_get_customer_id(struct i2c_client *client, u8 *pnum)
+{
+ return ft5402_read_reg(client, FT5402_REG_CUSTOMER_ID,
+ pnum);
+}
+
+static int ft5402_set_kx(struct i2c_client *client, u16 value)
+{
+ int err = 0;
+ err = ft5402_write_reg(client, FT5402_REG_KX_H,
+ value >> 8);
+ if (err < 0)
+ dev_err(&client->dev, "%s:set kx high failed\n",
+ __func__);
+ err = ft5402_write_reg(client, FT5402_REG_KX_L,
+ value);
+ if (err < 0)
+ dev_err(&client->dev, "%s:set kx low failed\n",
+ __func__);
+
+ return err;
+}
+
+static int ft5402_get_kx(struct i2c_client *client, u16 *pvalue)
+{
+ int err = 0;
+ u8 tmp1, tmp2;
+ err = ft5402_read_reg(client, FT5402_REG_KX_H,
+ &tmp1);
+ if (err < 0)
+ dev_err(&client->dev, "%s:get kx high failed\n",
+ __func__);
+ err = ft5402_read_reg(client, FT5402_REG_KX_L,
+ &tmp2);
+ if (err < 0)
+ dev_err(&client->dev, "%s:get kx low failed\n",
+ __func__);
+
+ *pvalue = ((u16)tmp1<<8) + (u16)tmp2;
+ return err;
+}
+static int ft5402_set_ky(struct i2c_client *client, u16 value)
+{
+ int err = 0;
+ err = ft5402_write_reg(client, FT5402_REG_KY_H,
+ value >> 8);
+ if (err < 0)
+ dev_err(&client->dev, "%s:set ky high failed\n",
+ __func__);
+ err = ft5402_write_reg(client, FT5402_REG_KY_L,
+ value);
+ if (err < 0)
+ dev_err(&client->dev, "%s:set ky low failed\n",
+ __func__);
+
+ return err;
+}
+
+static int ft5402_get_ky(struct i2c_client *client, u16 *pvalue)
+{
+ int err = 0;
+ u8 tmp1, tmp2;
+ err = ft5402_read_reg(client, FT5402_REG_KY_H,
+ &tmp1);
+ if (err < 0)
+ dev_err(&client->dev, "%s:get ky high failed\n",
+ __func__);
+ err = ft5402_read_reg(client, FT5402_REG_KY_L,
+ &tmp2);
+ if (err < 0)
+ dev_err(&client->dev, "%s:get ky low failed\n",
+ __func__);
+
+ *pvalue = ((u16)tmp1<<8) + (u16)tmp2;
+ return err;
+}
+static int ft5402_set_lemda_x(struct i2c_client *client, u8 value)
+{
+ return ft5402_write_reg(client, FT5402_REG_LEMDA_X,
+ value);
+}
+
+static int ft5402_get_lemda_x(struct i2c_client *client, u8 *pvalue)
+{
+ return ft5402_read_reg(client, FT5402_REG_LEMDA_X,
+ pvalue);
+}
+static int ft5402_set_lemda_y(struct i2c_client *client, u8 value)
+{
+ return ft5402_write_reg(client, FT5402_REG_LEMDA_Y,
+ value);
+}
+
+static int ft5402_get_lemda_y(struct i2c_client *client, u8 *pvalue)
+{
+ return ft5402_read_reg(client, FT5402_REG_LEMDA_Y,
+ pvalue);
+}
+static int ft5402_set_pos_x(struct i2c_client *client, u8 value)
+{
+ return ft5402_write_reg(client, FT5402_REG_DIRECTION,
+ value);
+}
+
+static int ft5402_get_pos_x(struct i2c_client *client, u8 *pvalue)
+{
+ return ft5402_read_reg(client, FT5402_REG_DIRECTION,
+ pvalue);
+}
+
+static int ft5402_set_scan_select(struct i2c_client *client, u8 value)
+{
+ return ft5402_write_reg(client, FT5402_REG_SCAN_SELECT,
+ value);
+}
+
+static int ft5402_get_scan_select(struct i2c_client *client, u8 *pvalue)
+{
+ return ft5402_read_reg(client, FT5402_REG_SCAN_SELECT,
+ pvalue);
+}
+
+static int ft5402_set_other_param(struct i2c_client *client)
+{
+ int err = 0;
+ err = ft5402_write_reg(client, FT5402_REG_THGROUP, (u8)(g_param_ft5402.ft5402_THGROUP));
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write THGROUP failed.\n", __func__);
+ return err;
+ }
+ err = ft5402_write_reg(client, FT5402_REG_THPEAK, g_param_ft5402.ft5402_THPEAK);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write THPEAK failed.\n",
+ __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_PWMODE_CTRL,
+ g_param_ft5402.ft5402_PWMODE_CTRL);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write PERIOD_CTRL failed.\n", __func__);
+ return err;
+ }
+ err = ft5402_write_reg(client, FT5402_REG_PERIOD_ACTIVE,
+ g_param_ft5402.ft5402_PERIOD_ACTIVE);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write PERIOD_ACTIVE failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FACE_DETECT_STATISTICS_TX_NUM,
+ g_param_ft5402.ft5402_FACE_DETECT_STATISTICS_TX_NUM);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FACE_DETECT_STATISTICS_TX_NUM failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_MAX_TOUCH_VALUE_HIGH,
+ g_param_ft5402.ft5402_MAX_TOUCH_VALUE>>8);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write MAX_TOUCH_VALUE_HIGH failed.\n", __func__);
+ return err;
+ }
+ err = ft5402_write_reg(client, FT5402_REG_MAX_TOUCH_VALUE_LOW,
+ g_param_ft5402.ft5402_MAX_TOUCH_VALUE);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write MAX_TOUCH_VALUE_LOW failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FACE_DETECT_MODE,
+ g_param_ft5402.ft5402_FACE_DETECT_MODE);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FACE_DETECT_MODE failed.\n", __func__);
+ return err;
+ }
+ err = ft5402_write_reg(client, FT5402_REG_DRAW_LINE_TH,
+ g_param_ft5402.ft5402_DRAW_LINE_TH);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write DRAW_LINE_TH failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_POINTS_SUPPORTED,
+ g_param_ft5402.ft5402_POINTS_SUPPORTED);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write POINTS_SUPPORTED failed.\n", __func__);
+ return err;
+ }
+ err = ft5402_write_reg(client, FT5402_REG_ESD_FILTER_FRAME,
+ g_param_ft5402.ft5402_ESD_FILTER_FRAME);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_ESD_FILTER_FRAME failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_POINTS_STABLE_MACRO,
+ g_param_ft5402.ft5402_POINTS_STABLE_MACRO);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_POINTS_STABLE_MACRO failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_MIN_DELTA_X,
+ g_param_ft5402.ft5402_MIN_DELTA_X);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_MIN_DELTA_X failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_MIN_DELTA_Y,
+ g_param_ft5402.ft5402_MIN_DELTA_Y);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_MIN_DELTA_Y failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_MIN_DELTA_STEP,
+ g_param_ft5402.ft5402_MIN_DELTA_STEP);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_MIN_DELTA_STEP failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_ESD_NOISE_MACRO,
+ g_param_ft5402.ft5402_ESD_NOISE_MACRO);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_ESD_NOISE_MACRO failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_ESD_DIFF_VAL,
+ g_param_ft5402.ft5402_ESD_DIFF_VAL);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_ESD_DIFF_VAL failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_ESD_NEGTIVE,
+ g_param_ft5402.ft5402_ESD_NEGTIVE);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_ESD_NEGTIVE failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_ESD_FILTER_FRAMES,
+ g_param_ft5402.ft5402_ESD_FILTER_FRAMES);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_ESD_FILTER_FRAMES failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_IO_LEVEL_SELECT,
+ g_param_ft5402.ft5402_IO_LEVEL_SELECT);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_IO_LEVEL_SELECT failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_POINTID_DELAY_COUNT,
+ g_param_ft5402.ft5402_POINTID_DELAY_COUNT);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_POINTID_DELAY_COUNT failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_LIFTUP_FILTER_MACRO,
+ g_param_ft5402.ft5402_LIFTUP_FILTER_MACRO);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_LIFTUP_FILTER_MACRO failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_DIFF_HANDLE_MACRO,
+ g_param_ft5402.ft5402_DIFF_HANDLE_MACRO);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_DIFF_HANDLE_MACRO failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_MIN_WATER,
+ g_param_ft5402.ft5402_MIN_WATER);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_MIN_WATER failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_MAX_NOISE,
+ g_param_ft5402.ft5402_MAX_NOISE);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_MAX_NOISE failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_WATER_START_RX,
+ g_param_ft5402.ft5402_WATER_START_RX);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_WATER_START_RX failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_WATER_START_TX,
+ g_param_ft5402.ft5402_WATER_START_TX);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_WATER_START_TX failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_HOST_NUMBER_SUPPORTED_MACRO,
+ g_param_ft5402.ft5402_HOST_NUMBER_SUPPORTED_MACRO);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_HOST_NUMBER_SUPPORTED_MACRO failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_RAISE_THGROUP,
+ g_param_ft5402.ft5402_RAISE_THGROUP);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_RAISE_THGROUP failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_CHARGER_STATE,
+ g_param_ft5402.ft5402_CHARGER_STATE);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_CHARGER_STATE failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_FILTERID_START,
+ g_param_ft5402.ft5402_FILTERID_START);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_FILTERID_START failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_FRAME_FILTER_EN_MACRO,
+ g_param_ft5402.ft5402_FRAME_FILTER_EN_MACRO);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_FRAME_FILTER_EN_MACRO failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_FRAME_FILTER_SUB_MAX_TH,
+ g_param_ft5402.ft5402_FRAME_FILTER_SUB_MAX_TH);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_FRAME_FILTER_SUB_MAX_TH failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_FRAME_FILTER_ADD_MAX_TH,
+ g_param_ft5402.ft5402_FRAME_FILTER_ADD_MAX_TH);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_FRAME_FILTER_ADD_MAX_TH failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_FRAME_FILTER_SKIP_START_FRAME,
+ g_param_ft5402.ft5402_FRAME_FILTER_SKIP_START_FRAME);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_FRAME_FILTER_SKIP_START_FRAME failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_FRAME_FILTER_BAND_EN,
+ g_param_ft5402.ft5402_FRAME_FILTER_BAND_EN);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_FRAME_FILTER_BAND_EN failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_FRAME_FILTER_BAND_WIDTH,
+ g_param_ft5402.ft5402_FRAME_FILTER_BAND_WIDTH);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_FRAME_FILTER_BAND_WIDTH failed.\n", __func__);
+ return err;
+ }
+
+ return err;
+}
+
+static int ft5402_get_other_param(struct i2c_client *client)
+{
+ int err = 0;
+ u8 value = 0x00;
+ err = ft5402_read_reg(client, FT5402_REG_THGROUP, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write THGROUP failed.\n", __func__);
+ return err;
+ } else
+ DBG("THGROUP=%02x\n", value);
+ err = ft5402_read_reg(client, FT5402_REG_THPEAK, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write THPEAK failed.\n",
+ __func__);
+ return err;
+ } else
+ DBG("THPEAK=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_PWMODE_CTRL, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write PWMODE_CTRL failed.\n", __func__);
+ return err;
+ } else
+ DBG("CTRL=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_PERIOD_ACTIVE,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write PERIOD_ACTIVE failed.\n", __func__);
+ return err;
+ } else
+ DBG("PERIOD_ACTIVE=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_MAX_TOUCH_VALUE_HIGH,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write MAX_TOUCH_VALUE_HIGH failed.\n", __func__);
+ return err;
+ } else
+ DBG("MAX_TOUCH_VALUE_HIGH=%02x\n", value);
+ err = ft5402_read_reg(client, FT5402_REG_MAX_TOUCH_VALUE_LOW,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write MAX_TOUCH_VALUE_LOW failed.\n", __func__);
+ return err;
+ } else
+ DBG("MAX_TOUCH_VALUE_LOW=%02x\n", value);
+ err = ft5402_read_reg(client, FT5402_REG_FACE_DETECT_MODE,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FACE_DETECT_MODE failed.\n", __func__);
+ return err;
+ } else
+ DBG("FACE_DEC_MODE=%02x\n", value);
+ err = ft5402_read_reg(client, FT5402_REG_DRAW_LINE_TH,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write DRAW_LINE_TH failed.\n", __func__);
+ return err;
+ } else
+ DBG("DRAW_LINE_TH=%02x\n", value);
+ err = ft5402_read_reg(client, FT5402_REG_POINTS_SUPPORTED,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_POINTS_SUPPORTED failed.\n", __func__);
+ return err;
+ } else
+ DBG("ft5402_POINTS_SUPPORTED=%02x\n", value);
+ err = ft5402_read_reg(client, FT5402_REG_ESD_FILTER_FRAME,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_ESD_FILTER_FRAME failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_ESD_FILTER_FRAME=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_POINTS_STABLE_MACRO,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_POINTS_STABLE_MACRO failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_POINTS_STABLE_MACRO=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_MIN_DELTA_X,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_MIN_DELTA_X failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_MIN_DELTA_X=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_MIN_DELTA_Y,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_MIN_DELTA_Y failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_MIN_DELTA_Y=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_MIN_DELTA_STEP,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_MIN_DELTA_STEP failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_MIN_DELTA_STEP=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_ESD_NOISE_MACRO,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_ESD_NOISE_MACRO failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_ESD_NOISE_MACRO=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_ESD_DIFF_VAL,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_ESD_DIFF_VAL failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_ESD_DIFF_VAL=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_ESD_NEGTIVE,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_ESD_NEGTIVE failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_ESD_NEGTIVE=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_ESD_FILTER_FRAMES,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_ESD_FILTER_FRAMES failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_ESD_FILTER_FRAMES=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_IO_LEVEL_SELECT,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_IO_LEVEL_SELECT failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_IO_LEVEL_SELECT=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_POINTID_DELAY_COUNT,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_POINTID_DELAY_COUNT failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_POINTID_DELAY_COUNT=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_LIFTUP_FILTER_MACRO,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_LIFTUP_FILTER_MACRO failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_LIFTUP_FILTER_MACRO=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_DIFF_HANDLE_MACRO,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_DIFF_HANDLE_MACRO failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_DIFF_HANDLE_MACRO=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_MIN_WATER,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_MIN_WATER failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_MIN_WATER=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_MAX_NOISE,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_MAX_NOISE failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_MAX_NOISE=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_WATER_START_RX,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_WATER_START_RX failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_WATER_START_RX=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_WATER_START_TX,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_WATER_START_TX failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_WATER_START_TX=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_HOST_NUMBER_SUPPORTED_MACRO,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_HOST_NUMBER_SUPPORTED_MACRO failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_HOST_NUMBER_SUPPORTED_MACRO=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_RAISE_THGROUP,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_RAISE_THGROUP failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_RAISE_THGROUP=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_CHARGER_STATE,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_CHARGER_STATE failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_CHARGER_STATE=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_FILTERID_START,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_FILTERID_START failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_FILTERID_START=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_FRAME_FILTER_EN_MACRO,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_FRAME_FILTER_EN_MACRO failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_FRAME_FILTER_EN_MACRO=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_FRAME_FILTER_SUB_MAX_TH,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_FRAME_FILTER_SUB_MAX_TH failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_FRAME_FILTER_SUB_MAX_TH=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_FRAME_FILTER_ADD_MAX_TH,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_FRAME_FILTER_ADD_MAX_TH failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_FRAME_FILTER_ADD_MAX_TH=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_FRAME_FILTER_SKIP_START_FRAME,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_FRAME_FILTER_SKIP_START_FRAME failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_FRAME_FILTER_SKIP_START_FRAME=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_FRAME_FILTER_BAND_EN,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_FRAME_FILTER_BAND_EN failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_FRAME_FILTER_BAND_EN=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_FRAME_FILTER_BAND_WIDTH,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_FRAME_FILTER_BAND_WIDTH failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_FRAME_FILTER_BAND_WIDTH=%02x\n", value);
+
+ return err;
+}
+int ft5402_get_ic_param(struct i2c_client *client)
+{
+ int err = 0;
+ int i = 0;
+ u8 value = 0x00;
+ u16 xvalue = 0x0000, yvalue = 0x0000;
+
+ /*enter factory mode*/
+ err = ft5402_write_reg(client, FT5402_REG_DEVICE_MODE, FT5402_FACTORYMODE_VALUE);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:enter factory mode failed.\n", __func__);
+ goto RETURN_WORK;
+ }
+
+ for (i = 0; i < g_ft5402_tx_num; i++) {
+ DBG("tx%d:", i);
+ /*get tx order*/
+ err = ft5402_get_tx_order(client, i, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get tx%d order.\n",
+ __func__, i);
+ goto RETURN_WORK;
+ }
+ DBG("order=%d ", value);
+ /*get tx cap*/
+ err = ft5402_get_tx_cap(client, i, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get tx%d cap.\n",
+ __func__, i);
+ goto RETURN_WORK;
+ }
+ DBG("cap=%02x\n", value);
+ }
+ /*get tx offset*/
+ err = ft5402_get_tx_offset(client, 0, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get tx 0 offset.\n",
+ __func__);
+ goto RETURN_WORK;
+ } else
+ DBG("tx offset = %02x\n", value);
+
+ /*get rx offset and cap*/
+ for (i = 0; i < g_ft5402_rx_num; i++) {
+ /*get rx order*/
+ DBG("rx%d:", i);
+ err = ft5402_get_rx_order(client, i, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get rx%d order.\n",
+ __func__, i);
+ goto RETURN_WORK;
+ }
+ DBG("order=%d ", value);
+ /*get rx cap*/
+ err = ft5402_get_rx_cap(client, i, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get rx%d cap.\n",
+ __func__, i);
+ goto RETURN_WORK;
+ }
+ DBG("cap=%02x ", value);
+ err = ft5402_get_rx_offset(client, i, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get rx offset.\n",
+ __func__);
+ goto RETURN_WORK;
+ }
+ DBG("offset=%02x\n", value);
+ }
+
+ /*get scan select*/
+ err = ft5402_get_scan_select(client, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get scan select.\n",
+ __func__);
+ goto RETURN_WORK;
+ } else
+ DBG("scan select = %02x\n", value);
+
+ /*get tx number*/
+ err = ft5402_get_tx_num(client, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get tx num.\n",
+ __func__);
+ goto RETURN_WORK;
+ } else
+ DBG("tx num = %02x\n", value);
+ /*get rx number*/
+ err = ft5402_get_rx_num(client, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get rx num.\n",
+ __func__);
+ goto RETURN_WORK;
+ } else
+ DBG("rx num = %02x\n", value);
+
+ /*get gain*/
+ err = ft5402_get_gain(client, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get gain.\n",
+ __func__);
+ goto RETURN_WORK;
+ } else
+ DBG("gain = %02x\n", value);
+ /*get voltage*/
+ err = ft5402_get_vol(client, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get voltage.\n",
+ __func__);
+ goto RETURN_WORK;
+ } else
+ DBG("voltage = %02x\n", value);
+ /*get start rx*/
+ err = ft5402_get_start_rx(client, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get start rx.\n",
+ __func__);
+ goto RETURN_WORK;
+ } else
+ DBG("start rx = %02x\n", value);
+ /*get adc target*/
+ err = ft5402_get_adc_target(client, &xvalue);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get adc target.\n",
+ __func__);
+ goto ERR_EXIT;
+ } else
+ DBG("ADC target = %02x\n", xvalue);
+
+
+RETURN_WORK:
+ /*enter work mode*/
+ err = ft5402_write_reg(client, FT5402_REG_DEVICE_MODE, FT5402_WORKMODE_VALUE);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:enter work mode failed.\n", __func__);
+ goto ERR_EXIT;
+ }
+
+ /*get resolution*/
+ err = ft5402_get_Resolution(client, &xvalue, &yvalue);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get resolution.\n",
+ __func__);
+ goto ERR_EXIT;
+ } else
+ DBG("resolution X = %d Y = %d\n", xvalue, yvalue);
+
+
+ /*get face detect statistics tx num*/
+ err = ft5402_get_face_detect_statistics_tx_num(client,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev,
+ "%s:could not get face detect statistics tx num.\n",
+ __func__);
+ goto ERR_EXIT;
+ } else
+ DBG("FT5402_FACE_DETECT_STATISTICS_TX_NUM = %02x\n", value);
+ /*get face detect pre value*/
+ err = ft5402_get_face_detect_pre_value(client,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev,
+ "%s:could not get face detect pre value.\n",
+ __func__);
+ goto ERR_EXIT;
+ } else
+ DBG("FT5402_FACE_DETECT_PRE_VALUE = %02x\n", value);
+ /*get face detect num*/
+ err = ft5402_get_face_detect_num(client, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get face detect num.\n",
+ __func__);
+ goto ERR_EXIT;
+ } else
+ DBG("face detect num = %02x\n", value);
+
+ /*get min peak value*/
+ err = ft5402_get_peak_value_min(client,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get min peak value.\n",
+ __func__);
+ goto ERR_EXIT;
+ } else
+ DBG("FT5402_BIGAREA_PEAK_VALUE_MIN = %02x\n", value);
+ /*get diff value over num*/
+ err = ft5402_get_diff_value_over_num(client,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get diff value over num.\n",
+ __func__);
+ goto ERR_EXIT;
+ } else
+ DBG("FT5402_BIGAREA_DIFF_VALUE_OVER_NUM = %02x\n", value);
+ /*get customer id*/
+ err = ft5402_get_customer_id(client,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get customer id.\n",
+ __func__);
+ goto ERR_EXIT;
+ } else
+ DBG("FT5402_CUSTOMER_ID = %02x\n", value);
+ /*get kx*/
+ err = ft5402_get_kx(client, &xvalue);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get kx.\n",
+ __func__);
+ goto ERR_EXIT;
+ } else
+ DBG("kx = %02x\n", xvalue);
+ /*get ky*/
+ err = ft5402_get_ky(client, &xvalue);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get ky.\n",
+ __func__);
+ goto ERR_EXIT;
+ } else
+ DBG("ky = %02x\n", xvalue);
+ /*get lemda x*/
+ err = ft5402_get_lemda_x(client,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get lemda x.\n",
+ __func__);
+ goto ERR_EXIT;
+ } else
+ DBG("lemda x = %02x\n", value);
+ /*get lemda y*/
+ err = ft5402_get_lemda_y(client,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get lemda y.\n",
+ __func__);
+ goto ERR_EXIT;
+ } else
+ DBG("lemda y = %02x\n", value);
+ /*get pos x*/
+ err = ft5402_get_pos_x(client, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get pos x.\n",
+ __func__);
+ goto ERR_EXIT;
+ } else
+ DBG("pos x = %02x\n", value);
+
+ err = ft5402_get_other_param(client);
+
+ERR_EXIT:
+ return err;
+}
+
+int ft5402_Init_IC_Param(struct i2c_client *client)
+{
+ int err = 0;
+ int i = 0;
+
+ /*enter factory mode*/
+ err = ft5402_write_reg(client, FT5402_REG_DEVICE_MODE, FT5402_FACTORYMODE_VALUE);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:enter factory mode failed.\n", __func__);
+ goto RETURN_WORK;
+ }
+
+ for (i = 0; i < g_ft5402_tx_num; i++) {
+ if (g_ft5402_tx_order[i] != 0xFF) {
+ /*set tx order*/
+ err = ft5402_set_tx_order(client, i, g_ft5402_tx_order[i]);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set tx%d order.\n",
+ __func__, i);
+ goto RETURN_WORK;
+ }
+ }
+ /*set tx cap*/
+ err = ft5402_set_tx_cap(client, i, g_ft5402_tx_cap[i]);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set tx%d cap.\n",
+ __func__, i);
+ goto RETURN_WORK;
+ }
+ }
+ /*set tx offset*/
+ err = ft5402_set_tx_offset(client, 0, g_ft5402_tx_offset);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set tx 0 offset.\n",
+ __func__);
+ goto RETURN_WORK;
+ }
+
+ /*set rx offset and cap*/
+ for (i = 0; i < g_ft5402_rx_num; i++) {
+ /*set rx order*/
+ err = ft5402_set_rx_order(client, i, g_ft5402_rx_order[i]);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set rx%d order.\n",
+ __func__, i);
+ goto RETURN_WORK;
+ }
+ /*set rx cap*/
+ err = ft5402_set_rx_cap(client, i, g_ft5402_rx_cap[i]);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set rx%d cap.\n",
+ __func__, i);
+ goto RETURN_WORK;
+ }
+ }
+ for (i = 0; i < g_ft5402_rx_num/2; i++) {
+ err = ft5402_set_rx_offset(client, i*2, g_ft5402_rx_offset[i]>>4);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set rx offset.\n",
+ __func__);
+ goto RETURN_WORK;
+ }
+ err = ft5402_set_rx_offset(client, i*2+1, g_ft5402_rx_offset[i]&0x0F);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set rx offset.\n",
+ __func__);
+ goto RETURN_WORK;
+ }
+ }
+
+ /*set scan select*/
+ err = ft5402_set_scan_select(client, g_ft5402_scanselect);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set scan select.\n",
+ __func__);
+ goto RETURN_WORK;
+ }
+
+ /*set tx number*/
+ err = ft5402_set_tx_num(client, g_ft5402_tx_num);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set tx num.\n",
+ __func__);
+ goto RETURN_WORK;
+ }
+ /*set rx number*/
+ err = ft5402_set_rx_num(client, g_ft5402_rx_num);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set rx num.\n",
+ __func__);
+ goto RETURN_WORK;
+ }
+
+ /*set gain*/
+ err = ft5402_set_gain(client, g_ft5402_gain);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set gain.\n",
+ __func__);
+ goto RETURN_WORK;
+ }
+ /*set voltage*/
+ err = ft5402_set_vol(client, g_ft5402_voltage);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set voltage.\n",
+ __func__);
+ goto RETURN_WORK;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_ADC_TARGET_HIGH,
+ g_param_ft5402.ft5402_ADC_TARGET>>8);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ADC_TARGET_HIGH failed.\n", __func__);
+ return err;
+ }
+ err = ft5402_write_reg(client, FT5402_REG_ADC_TARGET_LOW,
+ g_param_ft5402.ft5402_ADC_TARGET);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ADC_TARGET_LOW failed.\n", __func__);
+ return err;
+ }
+
+RETURN_WORK:
+ /*enter work mode*/
+ err = ft5402_write_reg(client, FT5402_REG_DEVICE_MODE, FT5402_WORKMODE_VALUE);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:enter work mode failed.\n", __func__);
+ goto ERR_EXIT;
+ }
+
+ /*set resolution*/
+ err = ft5402_set_Resolution(client, g_param_ft5402.ft5402_RESOLUTION_X,
+ g_param_ft5402.ft5402_RESOLUTION_Y);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set resolution.\n",
+ __func__);
+ goto ERR_EXIT;
+ }
+
+ /*set face detect statistics tx num*/
+ err = ft5402_set_face_detect_statistics_tx_num(client,
+ g_param_ft5402.ft5402_FACE_DETECT_STATISTICS_TX_NUM);
+ if (err < 0) {
+ dev_err(&client->dev,
+ "%s:could not set face detect statistics tx num.\n",
+ __func__);
+ goto ERR_EXIT;
+ }
+ /*set face detect pre value*/
+ err = ft5402_set_face_detect_pre_value(client,
+ g_param_ft5402.ft5402_FACE_DETECT_PRE_VALUE);
+ if (err < 0) {
+ dev_err(&client->dev,
+ "%s:could not set face detect pre value.\n",
+ __func__);
+ goto ERR_EXIT;
+ }
+ /*set face detect num*/
+ err = ft5402_set_face_detect_num(client,
+ g_param_ft5402.ft5402_FACE_DETECT_NUM);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set face detect num.\n",
+ __func__);
+ goto ERR_EXIT;
+ }
+
+ /*set min peak value*/
+ err = ft5402_set_peak_value_min(client,
+ g_param_ft5402.ft5402_BIGAREA_PEAK_VALUE_MIN);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set min peak value.\n",
+ __func__);
+ goto ERR_EXIT;
+ }
+ /*set diff value over num*/
+ err = ft5402_set_diff_value_over_num(client,
+ g_param_ft5402.ft5402_BIGAREA_DIFF_VALUE_OVER_NUM);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set diff value over num.\n",
+ __func__);
+ goto ERR_EXIT;
+ }
+ /*set customer id*/
+ err = ft5402_set_customer_id(client,
+ g_param_ft5402.ft5402_CUSTOMER_ID);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set customer id.\n",
+ __func__);
+ goto ERR_EXIT;
+ }
+ /*set kx*/
+ err = ft5402_set_kx(client, g_param_ft5402.ft5402_KX);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set kx.\n",
+ __func__);
+ goto ERR_EXIT;
+ }
+ /*set ky*/
+ err = ft5402_set_ky(client, g_param_ft5402.ft5402_KY);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set ky.\n",
+ __func__);
+ goto ERR_EXIT;
+ }
+ /*set lemda x*/
+ err = ft5402_set_lemda_x(client,
+ g_param_ft5402.ft5402_LEMDA_X);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set lemda x.\n",
+ __func__);
+ goto ERR_EXIT;
+ }
+ /*set lemda y*/
+ err = ft5402_set_lemda_y(client,
+ g_param_ft5402.ft5402_LEMDA_Y);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set lemda y.\n",
+ __func__);
+ goto ERR_EXIT;
+ }
+ /*set pos x*/
+ err = ft5402_set_pos_x(client, g_param_ft5402.ft5402_DIRECTION);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set pos x.\n",
+ __func__);
+ goto ERR_EXIT;
+ }
+
+ err = ft5402_set_other_param(client);
+
+ERR_EXIT:
+ return err;
+}
+
+
+char dst[512];
+static char * ft5402_sub_str(char * src, int n)
+{
+ char *p = src;
+ int i;
+ int m = 0;
+ int len = strlen(src);
+
+ while (n >= 1 && m <= len) {
+ i = 0;
+ dst[10] = ' ';
+ n--;
+ while ( *p != ',' && *p != ' ') {
+ dst[i++] = *(p++);
+ m++;
+ if (i >= len)
+ break;
+ }
+ dst[i++] = '\0';
+ p++;
+ }
+ return dst;
+}
+static int ft5402_GetInISize(char *config_name)
+{
+ struct file *pfile = NULL;
+ struct inode *inode;
+ unsigned long magic;
+ off_t fsize = 0;
+ char filepath[128];
+ memset(filepath, 0, sizeof(filepath));
+
+ sprintf(filepath, "%s%s", FT5402_INI_FILEPATH, config_name);
+
+ if (NULL == pfile)
+ pfile = filp_open(filepath, O_RDONLY, 0);
+
+ if (IS_ERR(pfile)) {
+ pr_err("error occured while opening file %s.\n", filepath);
+ return -EIO;
+ }
+
+ inode = pfile->f_dentry->d_inode;
+ magic = inode->i_sb->s_magic;
+ fsize = inode->i_size;
+ filp_close(pfile, NULL);
+ return fsize;
+}
+
+static int ft5x0x_ReadInIData(char *config_name,
+ char *config_buf)
+{
+ struct file *pfile = NULL;
+ struct inode *inode;
+ unsigned long magic;
+ off_t fsize;
+ char filepath[128];
+ loff_t pos;
+ mm_segment_t old_fs;
+
+ memset(filepath, 0, sizeof(filepath));
+ sprintf(filepath, "%s%s", FT5402_INI_FILEPATH, config_name);
+ if (NULL == pfile)
+ pfile = filp_open(filepath, O_RDONLY, 0);
+ if (IS_ERR(pfile)) {
+ pr_err("error occured while opening file %s.\n", filepath);
+ return -EIO;
+ }
+
+ inode = pfile->f_dentry->d_inode;
+ magic = inode->i_sb->s_magic;
+ fsize = inode->i_size;
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ pos = 0;
+ vfs_read(pfile, config_buf, fsize, &pos);
+ filp_close(pfile, NULL);
+ set_fs(old_fs);
+
+ return 0;
+}
+
+int ft5402_Get_Param_From_Ini(char *config_name)
+{
+ char key[64];
+ char value[512];
+ char section[64];
+ int i = 0;//,ret=0;
+ int j = 0;
+ char *filedata = NULL;
+ unsigned char legal_byte1 = 0x00;
+ unsigned char legal_byte2 = 0x00;
+
+ int inisize = ft5402_GetInISize(config_name);
+
+ if (inisize <= 0) {
+ pr_err("%s ERROR:Get firmware size failed\n",
+ __func__);
+ return -EIO;
+ }
+
+ filedata = kmalloc(inisize + 1, GFP_ATOMIC);
+
+ if (ft5x0x_ReadInIData(config_name, filedata)) {
+ pr_err("%s() - ERROR: request_firmware failed\n",
+ __func__);
+ kfree(filedata);
+ return -EIO;
+ }
+
+ /*check ini if it is illegal*/
+ sprintf(section, "%s", FT5402_APP_LEGAL);
+ sprintf(key, "%s", FT5402_APP_LEGAL_BYTE_1_STR);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ legal_byte1 = atoi(value);
+ DBG("legal_byte1=%s\n", value);
+ sprintf(key, "%s", FT5402_APP_LEGAL_BYTE_2_STR);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ legal_byte2 = atoi(value);
+ DBG("lega2_byte1=%s\n", value);
+ if(FT5402_APP_LEGAL_BYTE_1_VALUE == legal_byte1 &&
+ FT5402_APP_LEGAL_BYTE_2_VALUE == legal_byte2)
+ DBG("the ini file is valid\n");
+ else {
+ pr_err("[FTS]-----the ini file is invalid!please check it.\n");
+ goto ERROR_RETURN;
+ }
+
+ /*get ini param*/
+ sprintf(section, "%s", FT5402_APP_NAME);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_KX = atoi(value);
+ DBG("ft5402_KX=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_KY = atoi(value);
+ DBG("ft5402_KY=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_LEMDA_X = atoi(value);
+ DBG("ft5402_LEMDA_X=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_LEMDA_Y = atoi(value);
+ DBG("ft5402_LEMDA_Y=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_RESOLUTION_X = atoi(value);
+ DBG("ft5402_RESOLUTION_X=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_RESOLUTION_Y = atoi(value);
+ DBG("ft5402_RESOLUTION_Y=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_DIRECTION= atoi(value);
+ DBG("ft5402_DIRECTION=%s\n", value);
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_FACE_DETECT_PRE_VALUE = atoi(value);
+ DBG("ft5402_FACE_DETECT_PRE_VALUE=%s\n", value);
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_FACE_DETECT_NUM = atoi(value);
+ DBG("ft5402_FACE_DETECT_NUM=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_BIGAREA_PEAK_VALUE_MIN = atoi(value);/*The min value to be decided as the big point*/
+ DBG("ft5402_BIGAREA_PEAK_VALUE_MIN=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_BIGAREA_DIFF_VALUE_OVER_NUM = atoi(value);/*The min big points of the big area*/
+ DBG("ft5402_BIGAREA_DIFF_VALUE_OVER_NUM=%s\n", value);
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_CUSTOMER_ID = atoi(value);
+ DBG("ft5402_CUSTOM_ID=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_PERIOD_ACTIVE = atoi(value);
+ DBG("ft5402_PERIOD_ACTIVE=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_FACE_DETECT_STATISTICS_TX_NUM = atoi(value);
+ DBG("ft5402_FACE_DETECT_STATISTICS_TX_NUM=%s\n", value);
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_THGROUP = atoi(value);
+ DBG("ft5402_THGROUP=%s\n", value);
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_THPEAK = atoi(value);
+ DBG("ft5402_THPEAK=%s\n", value);
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_FACE_DETECT_MODE = atoi(value);
+ DBG("ft5402_FACE_DETECT_MODE=%s\n", value);
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_MAX_TOUCH_VALUE = atoi(value);
+ DBG("ft5402_MAX_TOUCH_VALUE=%s\n", value);
+
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_PWMODE_CTRL= atoi(value);
+ DBG("ft5402_PWMODE_CTRL=%s\n", value);
+
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+
+ i++;
+ g_param_ft5402.ft5402_DRAW_LINE_TH = atoi(value);
+ DBG("ft5402_DRAW_LINE_TH=%s\n", value);
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_POINTS_SUPPORTED= atoi(value);
+ DBG("ft5402_POINTS_SUPPORTED=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_START_RX = atoi(value);
+ DBG("ft5402_START_RX=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+
+ g_param_ft5402.ft5402_ADC_TARGET = atoi(value);
+ DBG("ft5402_ADC_TARGET=%s\n", value);
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+
+ g_param_ft5402.ft5402_ESD_FILTER_FRAME = atoi(value);
+ DBG("ft5402_ESD_FILTER_FRAME=%s\n", value);
+
+/*********************************************************************/
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_ft5402_tx_num = atoi(value);
+ DBG("ft5402_tx_num=%s\n", value);
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_ft5402_rx_num = atoi(value);
+ DBG("ft5402_rx_num=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_ft5402_gain = atoi(value);
+ DBG("ft5402_gain=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_ft5402_voltage = atoi(value);
+ DBG("ft5402_voltage=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_ft5402_scanselect = atoi(value);
+ DBG("ft5402_scanselect=%s\n", value);
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ for(j = 0; j < g_ft5402_tx_num; j++)
+ {
+ char * psrc = value;
+ g_ft5402_tx_order[j] = atoi(ft5402_sub_str(psrc, j+1));
+ }
+ DBG("ft5402_tx_order=%s\n", value);
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_ft5402_tx_offset = atoi(value);
+ DBG("ft5402_tx_offset=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ for(j = 0; j < g_ft5402_tx_num; j++)
+ {
+ char * psrc = value;
+ g_ft5402_tx_cap[j] = atoi(ft5402_sub_str(psrc, j+1));
+ }
+ DBG("ft5402_tx_cap=%s\n", value);
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ for(j = 0; j < g_ft5402_rx_num; j++)
+ {
+ char * psrc = value;
+ g_ft5402_rx_order[j] = atoi(ft5402_sub_str(psrc, j+1));
+ }
+ DBG("ft5402_rx_order=%s\n", value);
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ for(j = 0; j < g_ft5402_rx_num/2; j++)
+ {
+ char * psrc = value;
+ g_ft5402_rx_offset[j] = atoi(ft5402_sub_str(psrc, j+1));
+ }
+ DBG("ft5402_rx_offset=%s\n", value);
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ for(j = 0; j < g_ft5402_rx_num; j++)
+ {
+ char * psrc = value;
+ g_ft5402_rx_cap[j] = atoi(ft5402_sub_str(psrc, j+1));
+ }
+ DBG("ft5402_rx_cap=%s\n", value);
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_POINTS_STABLE_MACRO = atoi(value);
+ DBG("ft5402_POINTS_STABLE_MACRO=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_MIN_DELTA_X = atoi(value);
+ DBG("ft5402_MIN_DELTA_X=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_MIN_DELTA_Y = atoi(value);
+ DBG("ft5402_MIN_DELTA_Y=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_MIN_DELTA_STEP = atoi(value);
+ DBG("ft5402_MIN_DELTA_STEP=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_ESD_NOISE_MACRO = atoi(value);
+ DBG("ft5402_ESD_NOISE_MACRO=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_ESD_DIFF_VAL = atoi(value);
+ DBG("ft5402_ESD_DIFF_VAL=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_ESD_NEGTIVE = atoi(value);
+ DBG("ft5402_ESD_NEGTIVE=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_ESD_FILTER_FRAMES = atoi(value);
+ DBG("ft5402_ESD_FILTER_FRAMES=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_IO_LEVEL_SELECT = atoi(value);
+ DBG("ft5402_IO_LEVEL_SELECT=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_POINTID_DELAY_COUNT = atoi(value);
+ DBG("ft5402_POINTID_DELAY_COUNT=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_LIFTUP_FILTER_MACRO = atoi(value);
+ DBG("ft5402_LIFTUP_FILTER_MACRO=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_DIFF_HANDLE_MACRO = atoi(value);
+ DBG("ft5402_DIFF_HANDLE_MACRO=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_MIN_WATER = atoi(value);
+ DBG("ft5402_MIN_WATER=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_MAX_NOISE = atoi(value);
+ DBG("ft5402_MAX_NOISE=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_WATER_START_RX = atoi(value);
+ DBG("ft5402_WATER_START_RX=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_WATER_START_TX = atoi(value);
+ DBG("ft5402_WATER_START_TX=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_HOST_NUMBER_SUPPORTED_MACRO = atoi(value);
+ DBG("ft5402_HOST_NUMBER_SUPPORTED_MACRO=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_RAISE_THGROUP = atoi(value);
+ DBG("ft5402_RAISE_THGROUP=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_CHARGER_STATE = atoi(value);
+ DBG("ft5402_CHARGER_STATE=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_FILTERID_START = atoi(value);
+ DBG("ft5402_FILTERID_START=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_FRAME_FILTER_EN_MACRO = atoi(value);
+ DBG("ft5402_FRAME_FILTER_EN_MACRO=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_FRAME_FILTER_SUB_MAX_TH = atoi(value);
+ DBG("ft5402_FRAME_FILTER_SUB_MAX_TH=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_FRAME_FILTER_ADD_MAX_TH = atoi(value);
+ DBG("ft5402_FRAME_FILTER_ADD_MAX_TH=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_FRAME_FILTER_SKIP_START_FRAME = atoi(value);
+ DBG("ft5402_FRAME_FILTER_SKIP_START_FRAME=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_FRAME_FILTER_BAND_EN = atoi(value);
+ DBG("ft5402_FRAME_FILTER_BAND_EN=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_FRAME_FILTER_BAND_WIDTH = atoi(value);
+ DBG("ft5402_FRAME_FILTER_BAND_WIDTH=%s\n", value);
+
+
+ if (filedata)
+ kfree(filedata);
+ return 0;
+ERROR_RETURN:
+ if (filedata)
+ kfree(filedata);
+ return -1;
+}
+
diff --git a/drivers/input/touchscreen/ft6x0x/ft5402_config.h b/drivers/input/touchscreen/ft6x0x/ft5402_config.h
new file mode 100755
index 00000000..4d4935ed
--- /dev/null
+++ b/drivers/input/touchscreen/ft6x0x/ft5402_config.h
@@ -0,0 +1,71 @@
+#ifndef __FT5402_CONFIG_H__
+#define __FT5402_CONFIG_H__
+/*FT5402 config*/
+
+
+#define FT5402_START_RX 0
+#define FT5402_ADC_TARGET 8500
+#define FT5402_KX 120
+#define FT5402_KY 120
+#define FT5402_RESOLUTION_X 480
+#define FT5402_RESOLUTION_Y 800
+#define FT5402_LEMDA_X 0
+#define FT5402_LEMDA_Y 0
+#define FT5402_PWMODE_CTRL 1
+#define FT5402_POINTS_SUPPORTED 5
+#define FT5402_DRAW_LINE_TH 150
+#define FT5402_FACE_DETECT_MODE 0
+#define FT5402_FACE_DETECT_STATISTICS_TX_NUM 3
+#define FT5402_FACE_DETECT_PRE_VALUE 20
+#define FT5402_FACE_DETECT_NUM 10
+#define FT5402_THGROUP 25
+#define FT5402_THPEAK 60
+#define FT5402_BIGAREA_PEAK_VALUE_MIN 100
+#define FT5402_BIGAREA_DIFF_VALUE_OVER_NUM 50
+#define FT5402_MIN_DELTA_X 2
+#define FT5402_MIN_DELTA_Y 2
+#define FT5402_MIN_DELTA_STEP 2
+#define FT5402_ESD_DIFF_VAL 20
+#define FT5402_ESD_NEGTIVE -50
+#define FT5402_ESD_FILTER_FRAME 10
+#define FT5402_MAX_TOUCH_VALUE 600
+#define FT5402_CUSTOMER_ID 121
+#define FT5402_IO_LEVEL_SELECT 0
+#define FT5402_DIRECTION 1
+#define FT5402_POINTID_DELAY_COUNT 3
+#define FT5402_LIFTUP_FILTER_MACRO 1
+#define FT5402_POINTS_STABLE_MACRO 1
+#define FT5402_ESD_NOISE_MACRO 1
+#define FT5402_RV_G_PERIOD_ACTIVE 16
+#define FT5402_DIFFDATA_HANDLE 1
+#define FT5402_MIN_WATER_VAL -50
+#define FT5402_MAX_NOISE_VAL 10
+#define FT5402_WATER_HANDLE_START_RX 0
+#define FT5402_WATER_HANDLE_START_TX 0
+#define FT5402_HOST_NUMBER_SUPPORTED 1
+#define FT5402_RV_G_RAISE_THGROUP 30
+#define FT5402_RV_G_CHARGER_STATE 0
+#define FT5402_RV_G_FILTERID_START 2
+#define FT5402_FRAME_FILTER_EN 1
+#define FT5402_FRAME_FILTER_SUB_MAX_TH 2
+#define FT5402_FRAME_FILTER_ADD_MAX_TH 2
+#define FT5402_FRAME_FILTER_SKIP_START_FRAME 6
+#define FT5402_FRAME_FILTER_BAND_EN 1
+#define FT5402_FRAME_FILTER_BAND_WIDTH 128
+#define FT5402_OTP_PARAM_ID 0
+
+
+unsigned char g_ft5402_tx_num = 27;
+unsigned char g_ft5402_rx_num = 16;
+unsigned char g_ft5402_gain = 10;
+unsigned char g_ft5402_voltage = 3;
+unsigned char g_ft5402_scanselect = 8;
+unsigned char g_ft5402_tx_order[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26};
+unsigned char g_ft5402_tx_offset = 2;
+unsigned char g_ft5402_tx_cap[] = {42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42};
+unsigned char g_ft5402_rx_order[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+unsigned char g_ft5402_rx_offset[] = {68,68,68,68,68,68,68,68};
+unsigned char g_ft5402_rx_cap[] = {84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84};
+
+
+#endif \ No newline at end of file
diff --git a/drivers/input/touchscreen/ft6x0x/ft5402_ini_config.h b/drivers/input/touchscreen/ft6x0x/ft5402_ini_config.h
new file mode 100755
index 00000000..138f42e2
--- /dev/null
+++ b/drivers/input/touchscreen/ft6x0x/ft5402_ini_config.h
@@ -0,0 +1,411 @@
+#ifndef __LINUX_FT5402_INI_CONFIG_H__
+#define __LINUX_FT5402_INI_CONFIG_H
+
+
+/*Init param register address*/
+/*factory mode register from 14-131*/
+#define FT5402_REG_TX_NUM 0x03
+#define FT5402_REG_RX_NUM 0x04
+#define FT5402_REG_VOLTAGE 0x05
+#define FT5402_REG_GAIN 0x07
+#define FT5402_REG_SCAN_SELECT 0x4E
+#define FT5402_REG_TX_ORDER_START 0x50
+#define FT5402_REG_TX_CAP_START 0x78
+#define FT5402_REG_TX_OFFSET_START 0xBF
+#define FT5402_REG_RX_ORDER_START 0xeb
+#define FT5402_REG_RX_CAP_START 0xA0
+#define FT5402_REG_RX_OFFSET_START 0xD3
+#define FT5402_REG_START_RX 0x06
+#define FT5402_REG_ADC_TARGET_HIGH 0x08
+#define FT5402_REG_ADC_TARGET_LOW 0x09
+
+
+#define FT5402_REG_DEVICE_MODE 0x00
+
+
+/*work mode register from 0-13(0,1,12,13verify or Reserved)and 132-177(159 Reserved)*/
+#define FT5402_REG_THGROUP (0x00+0x80)
+#define FT5402_REG_THPEAK (0x01+0x80)
+#define FT5402_REG_PWMODE_CTRL (0x06+0x80)
+#define FT5402_REG_PERIOD_ACTIVE (0x59+0x80)
+#define FT5402_REG_POINTS_SUPPORTED (0x0A+0x80)
+#define FT5402_REG_ESD_FILTER_FRAME (0x4F+0x80)
+
+#define FT5402_REG_RESOLUTION_X_H (0x18+0x80)
+#define FT5402_REG_RESOLUTION_X_L (0x19+0x80)
+#define FT5402_REG_RESOLUTION_Y_H (0x1a+0x80)
+#define FT5402_REG_RESOLUTION_Y_L (0x1b+0x80)
+#define FT5402_REG_KX_H (0x1c+0x80)
+#define FT5402_REG_KX_L (0x9d)
+#define FT5402_REG_KY_H (0x9e)
+#define FT5402_REG_KY_L (0x1f+0x80)
+#define FT5402_REG_CUSTOMER_ID (0xA8)
+#define FT5402_REG_DRAW_LINE_TH (0xAe)
+#define FT5402_REG_FACE_DETECT_MODE (0xB0)
+#define FT5402_REG_MAX_TOUCH_VALUE_HIGH (0xD0)
+#define FT5402_REG_MAX_TOUCH_VALUE_LOW (0xD1)
+
+#define FT5402_REG_DIRECTION (0x53+0x80)
+#define FT5402_REG_LEMDA_X (0x41+0x80)
+#define FT5402_REG_LEMDA_Y (0x42+0x80)
+#define FT5402_REG_FACE_DETECT_STATISTICS_TX_NUM (0x43+0x80)
+#define FT5402_REG_FACE_DETECT_PRE_VALUE (0x44+0x80)
+#define FT5402_REG_FACE_DETECT_NUM (0x45+0x80)
+#define FT5402_REG_BIGAREA_PEAK_VALUE_MIN (0x33+0x80)
+#define FT5402_REG_BIGAREA_DIFF_VALUE_OVER_NUM (0x34+0x80)
+
+/**************************************************************************/
+#define FT5402_REG_FT5402_POINTS_STABLE_MACRO (0x57+0x80)
+#define FT5402_REG_FT5402_MIN_DELTA_X (0x4a+0x80)
+#define FT5402_REG_FT5402_MIN_DELTA_Y (0x4b+0x80)
+#define FT5402_REG_FT5402_MIN_DELTA_STEP (0x4c+0x80)
+
+#define FT5402_REG_FT5402_ESD_NOISE_MACRO (0x58+0x80)
+#define FT5402_REG_FT5402_ESD_DIFF_VAL (0x4d+0x80)
+#define FT5402_REG_FT5402_ESD_NEGTIVE (0xCe)
+#define FT5402_REG_FT5402_ESD_FILTER_FRAMES (0x4f+0x80)
+
+#define FT5402_REG_FT5402_IO_LEVEL_SELECT (0x52+0x80)
+
+#define FT5402_REG_FT5402_POINTID_DELAY_COUNT (0x54+0x80)
+
+#define FT5402_REG_FT5402_LIFTUP_FILTER_MACRO (0x55+0x80)
+
+#define FT5402_REG_FT5402_DIFF_HANDLE_MACRO (0x5A+0x80)
+#define FT5402_REG_FT5402_MIN_WATER (0x5B+0x80)
+#define FT5402_REG_FT5402_MAX_NOISE (0x5C+0x80)
+#define FT5402_REG_FT5402_WATER_START_RX (0x5D+0x80)
+#define FT5402_REG_FT5402_WATER_START_TX (0xDE)
+
+#define FT5402_REG_FT5402_HOST_NUMBER_SUPPORTED_MACRO (0x38+0x80)
+#define FT5402_REG_FT5402_RAISE_THGROUP (0x36+0x80)
+#define FT5402_REG_FT5402_CHARGER_STATE (0x35+0x80)
+
+#define FT5402_REG_FT5402_FILTERID_START (0x37+0x80)
+
+#define FT5402_REG_FT5402_FRAME_FILTER_EN_MACRO (0x5F+0x80)
+#define FT5402_REG_FT5402_FRAME_FILTER_SUB_MAX_TH (0x60+0x80)
+#define FT5402_REG_FT5402_FRAME_FILTER_ADD_MAX_TH (0x61+0x80)
+#define FT5402_REG_FT5402_FRAME_FILTER_SKIP_START_FRAME (0x62+0x80)
+#define FT5402_REG_FT5402_FRAME_FILTER_BAND_EN (0x63+0x80)
+#define FT5402_REG_FT5402_FRAME_FILTER_BAND_WIDTH (0x64+0x80)
+/**************************************************************************/
+
+#define FT5402_REG_TEST_MODE 0x04
+#define FT5402_REG_TEST_MODE_2 0x05
+#define FT5402_TX_TEST_MODE_1 0x28
+#define FT5402_RX_TEST_MODE_1 0x1E
+#define FT5402_FACTORYMODE_VALUE 0x40
+#define FT5402_WORKMODE_VALUE 0x00
+
+/************************************************************************/
+/* string */
+/************************************************************************/
+#define STRING_FT5402_KX "FT5X02_KX"
+#define STRING_FT5402_KY "FT5X02_KY"
+#define STRING_FT5402_LEMDA_X "FT5X02_LEMDA_X"
+#define STRING_FT5402_LEMDA_Y "FT5X02_LEMDA_Y"
+#define STRING_FT5402_RESOLUTION_X "FT5X02_RESOLUTION_X"
+#define STRING_FT5402_RESOLUTION_Y "FT5X02_RESOLUTION_Y"
+#define STRING_FT5402_DIRECTION "FT5X02_DIRECTION"
+
+
+
+#define STRING_FT5402_FACE_DETECT_PRE_VALUE "FT5X02_FACE_DETECT_PRE_VALUE"
+#define STRING_FT5402_FACE_DETECT_NUM "FT5X02_FACE_DETECT_NUM"
+#define STRING_FT5402_BIGAREA_PEAK_VALUE_MIN "FT5X02_BIGAREA_PEAK_VALUE_MIN"
+#define STRING_FT5402_BIGAREA_DIFF_VALUE_OVER_NUM "FT5X02_BIGAREA_DIFF_VALUE_OVER_NUM"
+#define STRING_FT5402_CUSTOMER_ID "FT5X02_CUSTOMER_ID"
+#define STRING_FT5402_PERIOD_ACTIVE "FT5X02_RV_G_PERIOD_ACTIVE"
+#define STRING_FT5402_FACE_DETECT_STATISTICS_TX_NUM "FT5X02_FACE_DETECT_STATISTICS_TX_NUM"
+
+#define STRING_FT5402_THGROUP "FT5X02_THGROUP"
+#define STRING_FT5402_THPEAK "FT5X02_THPEAK"
+#define STRING_FT5402_FACE_DETECT_MODE "FT5X02_FACE_DETECT_MODE"
+#define STRING_FT5402_MAX_TOUCH_VALUE "FT5X02_MAX_TOUCH_VALUE"
+
+#define STRING_FT5402_PWMODE_CTRL "FT5X02_PWMODE_CTRL"
+#define STRING_FT5402_DRAW_LINE_TH "FT5X02_DRAW_LINE_TH"
+
+#define STRING_FT5402_POINTS_SUPPORTED "FT5X02_POINTS_SUPPORTED"
+
+#define STRING_FT5402_START_RX "FT5X02_START_RX"
+#define STRING_FT5402_ADC_TARGET "FT5X02_ADC_TARGET"
+#define STRING_FT5402_ESD_FILTER_FRAME "FT5X02_ESD_FILTER_FRAME"
+
+#define STRING_FT5402_POINTS_STABLE_MACRO "FT5X02_POINTS_STABLE_MACRO"
+#define STRING_FT5402_MIN_DELTA_X "FT5X02_MIN_DELTA_X"
+#define STRING_FT5402_MIN_DELTA_Y "FT5X02_MIN_DELTA_Y"
+#define STRING_FT5402_MIN_DELTA_STEP "FT5X02_MIN_DELTA_STEP"
+
+#define STRING_FT5402_ESD_NOISE_MACRO "FT5X02_ESD_NOISE_MACRO"
+#define STRING_FT5402_ESD_DIFF_VAL "FT5X02_ESD_DIFF_VAL"
+#define STRING_FT5402_ESD_NEGTIVE "FT5X02_ESD_NEGTIVE"
+#define STRING_FT5402_ESD_FILTER_FRAME "FT5X02_ESD_FILTER_FRAME"
+
+#define STRING_FT5402_IO_LEVEL_SELECT "FT5X02_IO_LEVEL_SELECT"
+#define STRING_FT5402_POINTID_DELAY_COUNT "FT5X02_POINTID_DELAY_COUNT"
+
+#define STRING_FT5402_LIFTUP_FILTER_MACRO "FT5X02_LIFTUP_FILTER_MACRO"
+
+#define STRING_FT5402_DIFFDATA_HANDLE "FT5X02_DIFFDATA_HANDLE" //_MACRO
+#define STRING_FT5402_MIN_WATER_VAL "FT5X02_MIN_WATER_VAL"
+#define STRING_FT5402_MAX_NOISE_VAL "FT5X02_MAX_NOISE_VAL"
+#define STRING_FT5402_WATER_HANDLE_START_RX "FT5X02_WATER_HANDLE_START_RX"
+#define STRING_FT5402_WATER_HANDLE_START_TX "FT5X02_WATER_HANDLE_START_TX"
+
+#define STRING_FT5402_HOST_NUMBER_SUPPORTED "FT5X02_HOST_NUMBER_SUPPORTED"
+#define STRING_FT5402_RV_G_RAISE_THGROUP "FT5X02_RV_G_RAISE_THGROUP"
+#define STRING_FT5402_RV_G_CHARGER_STATE "FT5X02_RV_G_CHARGER_STATE"
+
+#define STRING_FT5402_RV_G_FILTERID_START "FT5X02_RV_G_FILTERID_START"
+
+#define STRING_FT5402_FRAME_FILTER_EN "FT5X02_FRAME_FILTER_EN"
+#define STRING_FT5402_FRAME_FILTER_SUB_MAX_TH "FT5X02_FRAME_FILTER_SUB_MAX_TH"
+#define STRING_FT5402_FRAME_FILTER_ADD_MAX_TH "FT5X02_FRAME_FILTER_ADD_MAX_TH"
+#define STRING_FT5402_FRAME_FILTER_SKIP_START_FRAME "FT5X02_FRAME_FILTER_SKIP_START_FRAME"
+#define STRING_FT5402_FRAME_FILTER_BAND_EN "FT5X02_FRAME_FILTER_BAND_EN"
+#define STRING_FT5402_FRAME_FILTER_BAND_WIDTH "FT5X02_FRAME_FILTER_BAND_WIDTH"
+
+
+#define STRING_ft5402_tx_num "FT5X02_tx_num"
+#define STRING_ft5402_rx_num "FT5X02_rx_num"
+#define STRING_ft5402_gain "FT5X02_gain"
+#define STRING_ft5402_voltage "FT5X02_voltage"
+#define STRING_ft5402_scanselect "FT5X02_scanselect"
+
+#define STRING_ft5402_tx_order "FT5X02_tx_order"
+#define STRING_ft5402_tx_offset "FT5X02_tx_offset"
+#define STRING_ft5402_tx_cap "FT5X02_tx_cap"
+
+#define STRING_ft5402_rx_order "FT5X02_rx_order"
+#define STRING_ft5402_rx_offset "FT5X02_rx_offset"
+#define STRING_ft5402_rx_cap "FT5X02_rx_cap"
+
+struct Struct_Param_FT5402 {
+ short ft5402_KX;
+ short ft5402_KY;
+ unsigned char ft5402_LEMDA_X;
+ unsigned char ft5402_LEMDA_Y;
+ short ft5402_RESOLUTION_X;
+ short ft5402_RESOLUTION_Y;
+ unsigned char ft5402_DIRECTION;
+ unsigned char ft5402_FACE_DETECT_PRE_VALUE;
+ unsigned char ft5402_FACE_DETECT_NUM;
+
+ unsigned char ft5402_BIGAREA_PEAK_VALUE_MIN;
+ unsigned char ft5402_BIGAREA_DIFF_VALUE_OVER_NUM;
+ unsigned char ft5402_CUSTOMER_ID;
+ unsigned char ft5402_PERIOD_ACTIVE;
+ unsigned char ft5402_FACE_DETECT_STATISTICS_TX_NUM;
+
+ short ft5402_THGROUP;
+ unsigned char ft5402_THPEAK;
+ unsigned char ft5402_FACE_DETECT_MODE;
+ short ft5402_MAX_TOUCH_VALUE;
+
+ unsigned char ft5402_PWMODE_CTRL;
+ unsigned char ft5402_DRAW_LINE_TH;
+ unsigned char ft5402_POINTS_SUPPORTED;
+
+ unsigned char ft5402_START_RX;
+ short ft5402_ADC_TARGET;
+ unsigned char ft5402_ESD_FILTER_FRAME;
+
+ unsigned char ft5402_POINTS_STABLE_MACRO;
+ unsigned char ft5402_MIN_DELTA_X;
+ unsigned char ft5402_MIN_DELTA_Y;
+ unsigned char ft5402_MIN_DELTA_STEP;
+
+ unsigned char ft5402_ESD_NOISE_MACRO;
+ unsigned char ft5402_ESD_DIFF_VAL;
+ char ft5402_ESD_NEGTIVE; //negtive
+ unsigned char ft5402_ESD_FILTER_FRAMES;
+
+ unsigned char ft5402_IO_LEVEL_SELECT;
+
+ unsigned char ft5402_POINTID_DELAY_COUNT;
+
+ unsigned char ft5402_LIFTUP_FILTER_MACRO;
+
+ unsigned char ft5402_DIFF_HANDLE_MACRO;
+ char ft5402_MIN_WATER; //negtive
+ unsigned char ft5402_MAX_NOISE;
+ unsigned char ft5402_WATER_START_RX;
+ unsigned char ft5402_WATER_START_TX;
+
+ unsigned char ft5402_HOST_NUMBER_SUPPORTED_MACRO;
+ unsigned char ft5402_RAISE_THGROUP;
+ unsigned char ft5402_CHARGER_STATE;
+
+ unsigned char ft5402_FILTERID_START;
+
+ unsigned char ft5402_FRAME_FILTER_EN_MACRO;
+ unsigned char ft5402_FRAME_FILTER_SUB_MAX_TH;
+ unsigned char ft5402_FRAME_FILTER_ADD_MAX_TH;
+ unsigned char ft5402_FRAME_FILTER_SKIP_START_FRAME;
+ unsigned char ft5402_FRAME_FILTER_BAND_EN;
+ unsigned char ft5402_FRAME_FILTER_BAND_WIDTH;
+
+};
+
+struct Struct_Param_FT5402 g_param_ft5402 = {
+ FT5402_KX,
+ FT5402_KY,
+ FT5402_LEMDA_X,
+ FT5402_LEMDA_Y,
+ FT5402_RESOLUTION_X,
+ FT5402_RESOLUTION_Y,
+ FT5402_DIRECTION,
+
+ FT5402_FACE_DETECT_PRE_VALUE,
+ FT5402_FACE_DETECT_NUM,
+ FT5402_BIGAREA_PEAK_VALUE_MIN,
+ FT5402_BIGAREA_DIFF_VALUE_OVER_NUM,
+ FT5402_CUSTOMER_ID,
+ FT5402_RV_G_PERIOD_ACTIVE,
+ FT5402_FACE_DETECT_STATISTICS_TX_NUM,
+
+ FT5402_THGROUP,
+ FT5402_THPEAK,
+ FT5402_FACE_DETECT_MODE,
+ FT5402_MAX_TOUCH_VALUE,
+
+ FT5402_PWMODE_CTRL,
+ FT5402_DRAW_LINE_TH,
+ FT5402_POINTS_SUPPORTED,
+
+ FT5402_START_RX,
+ FT5402_ADC_TARGET,
+ FT5402_ESD_FILTER_FRAME,
+
+ FT5402_POINTS_STABLE_MACRO,
+ FT5402_MIN_DELTA_X,
+ FT5402_MIN_DELTA_Y,
+ FT5402_MIN_DELTA_STEP,
+
+ FT5402_ESD_NOISE_MACRO,
+ FT5402_ESD_DIFF_VAL,
+ FT5402_ESD_NEGTIVE,
+ FT5402_ESD_FILTER_FRAME,
+
+ FT5402_IO_LEVEL_SELECT,
+
+ FT5402_POINTID_DELAY_COUNT,
+
+ FT5402_LIFTUP_FILTER_MACRO,
+
+ FT5402_DIFFDATA_HANDLE,
+ FT5402_MIN_WATER_VAL,
+ FT5402_MAX_NOISE_VAL,
+ FT5402_WATER_HANDLE_START_RX,
+ FT5402_WATER_HANDLE_START_TX,
+
+ FT5402_HOST_NUMBER_SUPPORTED,
+ FT5402_RV_G_RAISE_THGROUP,
+ FT5402_RV_G_CHARGER_STATE,
+
+ FT5402_RV_G_FILTERID_START,
+
+ FT5402_FRAME_FILTER_EN,
+ FT5402_FRAME_FILTER_SUB_MAX_TH,
+ FT5402_FRAME_FILTER_ADD_MAX_TH,
+ FT5402_FRAME_FILTER_SKIP_START_FRAME,
+ FT5402_FRAME_FILTER_BAND_EN,
+ FT5402_FRAME_FILTER_BAND_WIDTH,
+};
+
+char String_Param_FT5402[][64] = {
+ STRING_FT5402_KX,
+ STRING_FT5402_KY,
+ STRING_FT5402_LEMDA_X,
+ STRING_FT5402_LEMDA_Y,
+ STRING_FT5402_RESOLUTION_X,
+ STRING_FT5402_RESOLUTION_Y,
+ STRING_FT5402_DIRECTION,
+ STRING_FT5402_FACE_DETECT_PRE_VALUE,
+ STRING_FT5402_FACE_DETECT_NUM,
+ STRING_FT5402_BIGAREA_PEAK_VALUE_MIN,
+ STRING_FT5402_BIGAREA_DIFF_VALUE_OVER_NUM,
+ STRING_FT5402_CUSTOMER_ID,
+ STRING_FT5402_PERIOD_ACTIVE,
+ STRING_FT5402_FACE_DETECT_STATISTICS_TX_NUM,
+
+ STRING_FT5402_THGROUP,
+ STRING_FT5402_THPEAK,
+ STRING_FT5402_FACE_DETECT_MODE,
+ STRING_FT5402_MAX_TOUCH_VALUE,
+
+ STRING_FT5402_PWMODE_CTRL,
+ STRING_FT5402_DRAW_LINE_TH,
+ STRING_FT5402_POINTS_SUPPORTED,
+
+ STRING_FT5402_START_RX,
+ STRING_FT5402_ADC_TARGET,
+ STRING_FT5402_ESD_FILTER_FRAME,
+
+
+ STRING_ft5402_tx_num,
+ STRING_ft5402_rx_num,
+ STRING_ft5402_gain,
+ STRING_ft5402_voltage ,
+ STRING_ft5402_scanselect,
+
+ STRING_ft5402_tx_order,
+ STRING_ft5402_tx_offset,
+ STRING_ft5402_tx_cap,
+
+ STRING_ft5402_rx_order,
+ STRING_ft5402_rx_offset,
+ STRING_ft5402_rx_cap,
+
+ STRING_FT5402_POINTS_STABLE_MACRO,
+ STRING_FT5402_MIN_DELTA_X,
+ STRING_FT5402_MIN_DELTA_Y,
+ STRING_FT5402_MIN_DELTA_STEP,
+
+ STRING_FT5402_ESD_NOISE_MACRO,
+ STRING_FT5402_ESD_DIFF_VAL,
+ STRING_FT5402_ESD_NEGTIVE,
+ STRING_FT5402_ESD_FILTER_FRAME,
+
+ STRING_FT5402_IO_LEVEL_SELECT,
+
+ STRING_FT5402_POINTID_DELAY_COUNT,
+
+ STRING_FT5402_LIFTUP_FILTER_MACRO,
+
+ STRING_FT5402_DIFFDATA_HANDLE,
+ STRING_FT5402_MIN_WATER_VAL,
+ STRING_FT5402_MAX_NOISE_VAL,
+ STRING_FT5402_WATER_HANDLE_START_RX,
+ STRING_FT5402_WATER_HANDLE_START_TX,
+
+ STRING_FT5402_HOST_NUMBER_SUPPORTED,
+ STRING_FT5402_RV_G_RAISE_THGROUP,
+ STRING_FT5402_RV_G_CHARGER_STATE,
+
+ STRING_FT5402_RV_G_FILTERID_START,
+
+ STRING_FT5402_FRAME_FILTER_EN,
+ STRING_FT5402_FRAME_FILTER_SUB_MAX_TH,
+ STRING_FT5402_FRAME_FILTER_ADD_MAX_TH,
+ STRING_FT5402_FRAME_FILTER_SKIP_START_FRAME,
+ STRING_FT5402_FRAME_FILTER_BAND_EN,
+ STRING_FT5402_FRAME_FILTER_BAND_WIDTH,
+
+};
+
+#define FT5402_APP_NAME "FT5X02_param"
+
+#define FT5402_APP_LEGAL "Legal_File"
+#define FT5402_APP_LEGAL_BYTE_1_STR "BYTE_1"
+#define FT5402_APP_LEGAL_BYTE_2_STR "BYTE_2"
+
+#define FT5402_APP_LEGAL_BYTE_1_VALUE 107
+#define FT5402_APP_LEGAL_BYTE_2_VALUE 201
+
+
+#define FT5402_INI_FILEPATH "/system/etc/firmware/"
+
+#endif
diff --git a/drivers/input/touchscreen/ft6x0x/ft5x0x.c b/drivers/input/touchscreen/ft6x0x/ft5x0x.c
new file mode 100755
index 00000000..a3f6c4c9
--- /dev/null
+++ b/drivers/input/touchscreen/ft6x0x/ft5x0x.c
@@ -0,0 +1,896 @@
+/*
+ * drivers/input/touchscreen/ft5x0x/ft5x0x.c
+ *
+ * FocalTech ft5x0x TouchScreen driver.
+ *
+ * Copyright (c) 2010 Focal tech Ltd.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ *
+ * note: only support mulititouch Wenfs 2010-10-01
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <mach/hardware.h>
+#include <linux/platform_device.h>
+#include <linux/suspend.h>
+#include <linux/wait.h>
+#include <asm/uaccess.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <mach/wmt_iomux.h>
+#include <linux/slab.h>
+#include "ft5x0x.h"
+
+struct ft5x0x_data *pContext=NULL;
+static struct i2c_client *l_client=NULL;
+
+#ifdef TOUCH_KEY
+static int keycodes[NUM_KEYS] ={
+ KEY_MENU,
+ KEY_HOME,
+ KEY_BACK,
+ KEY_SEARCH
+};
+#endif
+
+#define FT5402_CONFIG_NAME "fttpconfig_5402public.ini"
+extern int ft5x0x_read_fw_ver(void);
+extern int ft5x0x_auto_clb(void);
+extern int ft5x0x_upg_fw_bin(struct ft5x0x_data *ft5x0x, int check_ver);
+extern int ft5402_Get_Param_From_Ini(char *config_name);
+extern int ft5402_Init_IC_Param(struct i2c_client *client);
+extern int ft5402_get_ic_param(struct i2c_client *client);
+extern int ft5402_read_reg(struct i2c_client * client, u8 regaddr, u8 * regvalue);
+static unsigned char ft5x0x_debug = 0;
+
+extern int fts_ctpm_fw_upgrade_with_i_file(struct i2c_client * client);
+int ft5x0x_i2c_rxdata(char *rxdata, int length)
+{
+ int ret;
+ struct i2c_msg msg[2];
+
+ msg[0].addr = pContext->addr;
+ msg[0].flags = 0 | I2C_M_NOSTART;
+ msg[0].len = 1;
+ msg[0].buf = rxdata;
+
+ msg[1].addr = pContext->addr;
+ msg[1].flags = I2C_M_RD;
+ msg[1].len = length;
+ msg[1].buf = rxdata;
+
+ ret = i2c_transfer(pContext->client->adapter, msg, 2);
+ if (ret <= 0)
+ dbg_err("msg i2c read error: %d\n", ret);
+
+ return ret;
+}
+
+
+int ft5x0x_i2c_txdata(char *txdata, int length)
+{
+ int ret;
+ struct i2c_msg msg[1];
+
+ msg[0].addr = pContext->addr;
+ msg[0].flags = 0;
+ msg[0].len = length;
+ msg[0].buf = txdata;
+
+ ret = i2c_transfer(pContext->client->adapter, msg, 1);
+ if (ret <= 0)
+ dbg_err("msg i2c read error: %d\n", ret);
+
+ return ret;
+}
+
+static void ft5x0x_penup(struct ft5x0x_data *ft5x0x)
+{
+ input_mt_sync(ft5x0x->input_dev);
+ input_sync(ft5x0x->input_dev);
+#ifdef TOUCH_KEY
+ if(ft5x0x->tskey_used && ft5x0x->tkey_pressed && ft5x0x->tkey_idx < NUM_KEYS ){
+ input_report_key(ft5x0x->input_dev, keycodes[ft5x0x->tkey_idx], 1);
+ input_sync(ft5x0x->input_dev);
+ input_report_key(ft5x0x->input_dev, keycodes[ft5x0x->tkey_idx], 0);
+ input_sync(ft5x0x->input_dev);
+ dbg("report as key event %d \n",ft5x0x->tkey_idx);
+ }
+#endif
+
+ dbg("pen up\n");
+ return;
+}
+
+#ifdef TOUCH_KEY
+static int ft5x0x_read_tskey(struct ft5x0x_data *ft5x0x,int x,int y)
+{
+ int px,py;
+
+ if(ft5x0x->tkey.axis){
+ px = y;
+ py = x;
+ }else{
+ px = x;
+ py = y;
+ }
+
+ if(px >= ft5x0x->tkey.x_lower && px<=ft5x0x->tkey.x_upper){
+ ft5x0x->tkey_pressed = 1;
+ if(py>= ft5x0x->tkey.ypos[0].y_lower && py<= ft5x0x->tkey.ypos[0].y_upper){
+ ft5x0x->tkey_idx= 0;
+ }else if(py>= ft5x0x->tkey.ypos[1].y_lower && py<= ft5x0x->tkey.ypos[1].y_upper){
+ ft5x0x->tkey_idx = 1;
+ }else if(py>= ft5x0x->tkey.ypos[2].y_lower && py<= ft5x0x->tkey.ypos[2].y_upper){
+ ft5x0x->tkey_idx = 2;
+ }else if(py>= ft5x0x->tkey.ypos[3].y_lower && py<= ft5x0x->tkey.ypos[3].y_upper){
+ ft5x0x->tkey_idx = 3;
+ }else{
+ ft5x0x->tkey_idx = NUM_KEYS;
+ }
+
+ return 1;
+ }
+
+ ft5x0x->tkey_pressed = 0;
+ return 0;
+}
+#endif
+
+static int ft5x0x_read_data(struct ft5x0x_data *ft5x0x)
+{
+ int ret = -1;
+ int i = 0;
+ u16 x,y,px,py;
+ u8 buf[64] = {0}, id;
+ struct ts_event *event = &ft5x0x->event;
+
+ if(ft5x0x->nt == 10)
+ ret = ft5x0x_i2c_rxdata(buf, 64);
+ else if(ft5x0x->nt == 5)
+ ret = ft5x0x_i2c_rxdata(buf, 31);
+
+ if (ret <= 0) {
+ dbg_err("read_data i2c_rxdata failed: %d\n", ret);
+ return ret;
+ }
+
+ memset(event, 0, sizeof(struct ts_event));
+ //event->tpoint = buf[2] & 0x03;// 0000 0011
+ //event->tpoint = buf[2] & 0x07;// 000 0111
+ event->tpoint = buf[2]&0x0F;
+ if (event->tpoint == 0) {
+ ft5x0x_penup(ft5x0x);
+ return 1;
+ }
+
+ if (event->tpoint > ft5x0x->nt){
+ dbg_err("tounch pointnum=%d > max:%d\n", event->tpoint,ft5x0x->nt);
+ return -1;
+ }
+
+ for (i = 0; i < event->tpoint; i++){
+ id = (buf[5+i*6] >>4) & 0x0F;//get track id
+ if(ft5x0x->swap){
+ px = (buf[3+i*6] & 0x0F)<<8 |buf[4+i*6];
+ py = (buf[5+i*6] & 0x0F)<<8 |buf[6+i*6];
+ }else{
+ px = (buf[5+i*6] & 0x0F)<<8 |buf[6+i*6];
+ py = (buf[3+i*6] & 0x0F)<<8 |buf[4+i*6];
+ }
+
+ x = px;
+ y = py;
+
+ if(ft5x0x->xch)
+ x = ft5x0x->reslx - px;
+
+ if(ft5x0x->ych)
+ y = ft5x0x->resly - py;
+
+ if(ft5x0x->dbg) printk("F%d: Tid=%d,px=%d,py=%d; x=%d,y=%d\n", i, id, px, py, x, y);
+
+#ifdef TOUCH_KEY
+ if(ft5x0x->tskey_used && event->tpoint==1) {
+ if(ft5x0x_read_tskey(ft5x0x,px,py) > 0) return -1;
+ }
+#endif
+ event->x[i] = x;
+ event->y[i] = y;
+ event->tid[i] = id;
+
+ }
+
+ return 0;
+}
+
+static void ft5x0x_report(struct ft5x0x_data *ft5x0x)
+{
+ int i = 0;
+ struct ts_event *event = &ft5x0x->event;
+
+ for (i = 0; i < event->tpoint; i++){
+ input_report_abs(ft5x0x->input_dev, ABS_MT_TRACKING_ID, event->tid[i]);
+ input_report_abs(ft5x0x->input_dev, ABS_MT_POSITION_X, event->x[i]);
+ input_report_abs(ft5x0x->input_dev, ABS_MT_POSITION_Y, event->y[i]);
+ input_mt_sync(ft5x0x->input_dev);
+ }
+ input_sync(ft5x0x->input_dev);
+
+ return;
+}
+
+static void ft5x0x_read_work(struct work_struct *work)
+{
+ int ret = -1;
+ struct ft5x0x_data *ft5x0x = container_of(work, struct ft5x0x_data, read_work);
+
+ mutex_lock(&ft5x0x->ts_mutex);
+ ret = ft5x0x_read_data(ft5x0x);
+
+ if (ret == 0) ft5x0x_report(ft5x0x);
+
+ wmt_gpio_unmask_irq(ft5x0x->irqgpio);
+ mutex_unlock(&ft5x0x->ts_mutex);
+
+ return;
+}
+
+static irqreturn_t ft5x0x_interrupt(int irq, void *dev)
+{
+ struct ft5x0x_data *ft5x0x = dev;
+
+ if (gpio_irqstatus(ft5x0x->irqgpio))
+ {
+
+ if(ft5x0x_debug == 1)
+ {
+ printk("++++++++++++%s\n",__func__);
+ }
+ wmt_gpio_ack_irq(ft5x0x->irqgpio);
+ if (is_gpio_irqenable(ft5x0x->irqgpio))
+ {
+ wmt_gpio_mask_irq(ft5x0x->irqgpio);
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ if(!ft5x0x->earlysus) queue_work(ft5x0x->workqueue, &ft5x0x->read_work);
+#else
+ queue_work(ft5x0x->workqueue, &ft5x0x->read_work);
+#endif
+
+ }
+ return IRQ_HANDLED;
+ }
+ return IRQ_NONE;
+}
+
+static void ft5x0x_reset(struct ft5x0x_data *ft5x0x)
+{
+ gpio_set_value(ft5x0x->rstgpio, 1);
+ mdelay(5);
+ gpio_set_value(ft5x0x->rstgpio, 0);
+ mdelay(20);
+ gpio_set_value(ft5x0x->rstgpio, 1);
+ mdelay(5);
+
+ return;
+}
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void ft5x0x_early_suspend(struct early_suspend *handler)
+{
+ struct ft5x0x_data *ft5x0x = container_of(handler, struct ft5x0x_data, early_suspend);
+ ft5x0x->earlysus = 1;
+ wmt_gpio_mask_irq(ft5x0x->irqgpio);
+ return;
+}
+
+static void ft5x0x_late_resume(struct early_suspend *handler)
+{
+ struct ft5x0x_data *ft5x0x = container_of(handler, struct ft5x0x_data, early_suspend);
+
+ ft5x0x_reset(ft5x0x);
+ ft5x0x->earlysus = 0;
+
+ wmt_gpio_set_irq_type(ft5x0x->irqgpio, IRQ_TYPE_EDGE_FALLING);
+ wmt_gpio_unmask_irq(ft5x0x->irqgpio);
+
+ return;
+}
+#endif //CONFIG_HAS_EARLYSUSPEND
+
+#ifdef CONFIG_PM
+static int ft5x0x_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct ft5x0x_data *ft5x0x = dev_get_drvdata(&pdev->dev);
+ ft5x0x->earlysus = 1;
+ wmt_gpio_mask_irq(ft5x0x->irqgpio);
+ return 0;
+}
+
+static int ft5x0x_resume(struct platform_device *pdev)
+{
+ struct ft5x0x_data *ft5x0x = dev_get_drvdata(&pdev->dev);
+ ft5x0x_reset(ft5x0x);
+ ft5x0x->earlysus = 0;
+
+ if (ft5x0x->load_cfg) {
+ msleep(350);
+ ft5402_Init_IC_Param(ft5x0x->client);
+ //msleep(50);
+ ft5402_get_ic_param(ft5x0x->client);
+ }
+ wmt_gpio_set_irq_type(ft5x0x->irqgpio, IRQ_TYPE_EDGE_FALLING);
+ wmt_gpio_unmask_irq(ft5x0x->irqgpio);
+ return 0;
+}
+
+#else
+#define ft5x0x_suspend NULL
+#define ft5x0x_resume NULL
+#endif
+
+static ssize_t cat_dbg(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "dbg \n");
+}
+
+static ssize_t echo_dbg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ unsigned int dbg = simple_strtoul(buf, NULL, 10);
+ struct ft5x0x_data *ft5x0x = pContext;
+
+ if(dbg){
+ ft5x0x->dbg = 1;
+ }else{
+ ft5x0x->dbg = 0;
+ }
+
+ return count;
+}
+static DEVICE_ATTR(dbg, S_IRUGO | S_IWUSR, cat_dbg, echo_dbg);
+
+static ssize_t cat_clb(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "calibrate \n");
+}
+
+static ssize_t echo_clb(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ unsigned int cal = simple_strtoul(buf, NULL, 10);
+
+ if(cal){
+ if(ft5x0x_auto_clb()) printk("Calibrate Failed.\n");
+ }else{
+ printk("calibrate --echo 1 >clb.\n");
+ }
+
+ return count;
+}
+
+static DEVICE_ATTR(clb, S_IRUGO | S_IWUSR, cat_clb, echo_clb);
+
+static ssize_t cat_fupg(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "fupg \n");
+}
+
+static ssize_t echo_fupg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct ft5x0x_data *ft5x0x = pContext;
+ unsigned int upg = simple_strtoul(buf, NULL, 10);
+
+ wmt_gpio_mask_irq(ft5x0x->irqgpio);
+ if(upg){
+ if(ft5x0x_upg_fw_bin(ft5x0x, 0)) printk("Upgrade Failed.\n");
+ }else{
+ printk("upgrade --echo 1 > fupg.\n");
+ }
+ wmt_gpio_unmask_irq(ft5x0x->irqgpio);
+
+ return count;
+}
+static DEVICE_ATTR(fupg, S_IRUGO | S_IWUSR, cat_fupg, echo_fupg);
+
+
+static ssize_t cat_fver(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int fw_ver = ft5x0x_read_fw_ver();
+ return sprintf(buf, "firmware version:0x%02x \n",fw_ver);
+}
+
+static ssize_t echo_fver(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ return count;
+}
+static DEVICE_ATTR(fver, S_IRUGO | S_IWUSR, cat_fver, echo_fver);
+
+static ssize_t cat_addr(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int ret;
+ u8 addrs[32];
+ int cnt=0;
+ struct i2c_msg msg[2];
+ struct ft5x0x_data *ft5x0x = pContext;
+ u8 ver[1]= {0xa6};
+
+ ft5x0x->addr = 1;
+
+ msg[0].addr = ft5x0x->addr;
+ msg[0].flags = 0;
+ msg[0].len = 1;
+ msg[0].buf = ver;
+
+ msg[1].addr = ft5x0x->addr;
+ msg[1].flags = I2C_M_RD;
+ msg[1].len = 1;
+ msg[1].buf = ver;
+
+ while(ft5x0x->addr < 0x80){
+ ret = i2c_transfer(ft5x0x->client->adapter, msg, 2);
+ if(ret == 2) sprintf(&addrs[5*cnt++], " 0x%02x",ft5x0x->addr);
+
+ ft5x0x->addr++;
+ msg[0].addr = msg[1].addr = ft5x0x->addr;
+ }
+
+ return sprintf(buf, "i2c addr:%s\n",addrs);
+}
+
+static ssize_t echo_addr(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ unsigned int addr;
+ struct ft5x0x_data *ft5x0x = pContext;
+
+ sscanf(buf,"%x", &addr);
+ ft5x0x->addr = addr;
+
+ return count;
+}
+static DEVICE_ATTR(addr, S_IRUGO | S_IWUSR, cat_addr, echo_addr);
+
+static struct attribute *ft5x0x_attributes[] = {
+ &dev_attr_clb.attr,
+ &dev_attr_fupg.attr,
+ &dev_attr_fver.attr,
+ &dev_attr_dbg.attr,
+ &dev_attr_addr.attr,
+ NULL
+};
+
+static const struct attribute_group ft5x0x_group = {
+ .attrs = ft5x0x_attributes,
+};
+
+static int ft5x0x_sysfs_create_group(struct ft5x0x_data *ft5x0x, const struct attribute_group *group)
+{
+ int err;
+
+ ft5x0x->kobj = kobject_create_and_add("wmtts", NULL) ;
+ if(!ft5x0x->kobj){
+ dbg_err("kobj create failed.\n");
+ return -ENOMEM;
+ }
+
+ /* Register sysfs hooks */
+ err = sysfs_create_group(ft5x0x->kobj, group);
+ if (err < 0){
+ kobject_del(ft5x0x->kobj);
+ dbg_err("Create sysfs group failed!\n");
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static void ft5x0x_sysfs_remove_group(struct ft5x0x_data *ft5x0x, const struct attribute_group *group)
+{
+ sysfs_remove_group(ft5x0x->kobj, group);
+ kobject_del(ft5x0x->kobj);
+ return;
+}
+
+static int ft5x0x_probe(struct platform_device *pdev)
+{
+ int i,err = 0;
+ u8 value = 0;
+ u8 cfg_name[32];
+ struct ft5x0x_data *ft5x0x = platform_get_drvdata( pdev);
+
+ ft5x0x->client = l_client;
+ INIT_WORK(&ft5x0x->read_work, ft5x0x_read_work);
+ mutex_init(&ft5x0x->ts_mutex);
+
+ ft5x0x->workqueue = create_singlethread_workqueue(ft5x0x->name);
+ if (!ft5x0x->workqueue) {
+ err = -ESRCH;
+ goto exit_create_singlethread;
+ }
+
+ err = ft5x0x_sysfs_create_group(ft5x0x, &ft5x0x_group);
+ if(err < 0){
+ dbg("create sysfs group failed.\n");
+ goto exit_create_group;
+ }
+
+ ft5x0x->input_dev = input_allocate_device();
+ if (!ft5x0x->input_dev) {
+ err = -ENOMEM;
+ dbg("failed to allocate input device\n");
+ goto exit_input_dev_alloc_failed;
+ }
+
+ ft5x0x->input_dev->name = ft5x0x->name;
+ ft5x0x->input_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ set_bit(INPUT_PROP_DIRECT, ft5x0x->input_dev->propbit);
+
+ input_set_abs_params(ft5x0x->input_dev,
+ ABS_MT_POSITION_X, 0, ft5x0x->reslx, 0, 0);
+ input_set_abs_params(ft5x0x->input_dev,
+ ABS_MT_POSITION_Y, 0, ft5x0x->resly, 0, 0);
+ input_set_abs_params(ft5x0x->input_dev,
+ ABS_MT_TRACKING_ID, 0, 20, 0, 0);
+#ifdef TOUCH_KEY
+ if(ft5x0x->tskey_used){
+ for (i = 0; i <NUM_KEYS; i++)
+ set_bit(keycodes[i], ft5x0x->input_dev->keybit);
+
+ ft5x0x->input_dev->keycode = keycodes;
+ ft5x0x->input_dev->keycodesize = sizeof(unsigned int);
+ ft5x0x->input_dev->keycodemax = NUM_KEYS;
+ }
+#endif
+
+ err = input_register_device(ft5x0x->input_dev);
+ if (err) {
+ dbg_err("ft5x0x_ts_probe: failed to register input device.\n");
+ goto exit_input_register_device_failed;
+ }
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ ft5x0x->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
+ ft5x0x->early_suspend.suspend = ft5x0x_early_suspend;
+ ft5x0x->early_suspend.resume = ft5x0x_late_resume;
+ register_early_suspend(&ft5x0x->early_suspend);
+#endif
+
+ if(ft5x0x->upg){
+ if (fts_ctpm_fw_upgrade_with_i_file(ft5x0x->client) < 0) {
+ printk("ft5x0x_probe -----upgrade failed!-\n");
+ }
+ else
+ {
+ printk("ft5x0x_probe -----upgrade successful!-\n");
+ wmt_setsyspara("wmt.io.ts.upg","");
+ ft5x0x_reset(ft5x0x);
+ }
+ ft5x0x->upg = 0x00;
+ }
+
+ if(request_irq(ft5x0x->irq, ft5x0x_interrupt, IRQF_SHARED, ft5x0x->name, ft5x0x) < 0){
+ dbg_err("Could not allocate irq for ts_ft5x0x !\n");
+ err = -1;
+ goto exit_register_irq;
+ }
+
+ { // check if need to load config to IC or not
+ err = ft5402_read_reg(ft5x0x->client, 0xa3, &value);
+ if (err < 0)
+ dbg_err("Read reg 0xa3 failed.\n");
+ else
+ printk("0xa3 reg = %d\n", value);
+ if (value == 3)
+ ft5x0x->load_cfg = 1;
+ else
+ ft5x0x->load_cfg = 0;
+ }
+ ft5x0x_reset(ft5x0x);
+
+ if (ft5x0x->load_cfg) {
+ msleep(350); /*make sure CTP already finish startup process*/
+ sprintf(cfg_name, "%s.ini", ft5x0x->cfg_name);
+ printk("Config file name: %s\n", cfg_name);
+ if (ft5402_Get_Param_From_Ini(cfg_name) >= 0)
+ ft5402_Init_IC_Param(ft5x0x->client);
+ else
+ dbg_err("[FTS]-------Get ft5402 param from INI file failed\n");
+ ft5402_get_ic_param(ft5x0x->client);
+ }
+
+ wmt_gpio_set_irq_type(ft5x0x->irqgpio, IRQ_TYPE_EDGE_FALLING);
+ wmt_gpio_unmask_irq(ft5x0x->irqgpio);
+
+
+ return 0;
+
+exit_register_irq:
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ unregister_early_suspend(&ft5x0x->early_suspend);
+#endif
+exit_input_register_device_failed:
+ input_free_device(ft5x0x->input_dev);
+exit_input_dev_alloc_failed:
+ ft5x0x_sysfs_remove_group(ft5x0x, &ft5x0x_group);
+exit_create_group:
+ cancel_work_sync(&ft5x0x->read_work);
+ destroy_workqueue(ft5x0x->workqueue);
+exit_create_singlethread:
+ return err;
+}
+
+static int ft5x0x_remove(struct platform_device *pdev)
+{
+ struct ft5x0x_data *ft5x0x = platform_get_drvdata( pdev);
+
+ cancel_work_sync(&ft5x0x->read_work);
+ flush_workqueue(ft5x0x->workqueue);
+ destroy_workqueue(ft5x0x->workqueue);
+
+ free_irq(ft5x0x->irq, ft5x0x);
+ wmt_gpio_mask_irq(ft5x0x->irqgpio);
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ unregister_early_suspend(&ft5x0x->early_suspend);
+#endif
+ input_unregister_device(ft5x0x->input_dev);
+
+ ft5x0x_sysfs_remove_group(ft5x0x, &ft5x0x_group);
+
+ mutex_destroy(&ft5x0x->ts_mutex);
+ dbg("remove...\n");
+ return 0;
+}
+
+static void ft5x0x_release(struct device *device)
+{
+ return;
+}
+
+static struct platform_device ft5x0x_device = {
+ .name = DEV_FT5X0X,
+ .id = 0,
+ .dev = {.release = ft5x0x_release},
+};
+
+static struct platform_driver ft5x0x_driver = {
+ .driver = {
+ .name = DEV_FT5X0X,
+ .owner = THIS_MODULE,
+ },
+ .probe = ft5x0x_probe,
+ .remove = ft5x0x_remove,
+ .suspend = ft5x0x_suspend,
+ .resume = ft5x0x_resume,
+};
+
+static int check_touch_env(struct ft5x0x_data *ft5x0x)
+{
+ int i,ret = 0;
+ int len = 96;
+ int Enable;
+ char retval[96] = {0};
+ char *p=NULL;
+ char *s=NULL;
+
+ // Get u-boot parameter
+ ret = wmt_getsyspara("wmt.io.touch", retval, &len);
+ if(ret){
+ //printk("MST FT5x0x:Read wmt.io.touch Failed.\n");
+ return -EIO;
+ }
+ sscanf(retval,"%d:",&Enable);
+ //check touch enable
+ if(Enable == 0){
+ //printk("FT5x0x Touch Screen Is Disabled.\n");
+ return -ENODEV;
+ }
+
+ p = strchr(retval,':');
+ p++;
+ if(strncmp(p,"ft5301",6)==0){//check touch ID
+ ft5x0x->id = FT5301;
+ ft5x0x->name = DEV_FT5301;
+ }else if(strncmp(p,"ft5406",6)==0){
+ ft5x0x->id = FT5406;
+ ft5x0x->name = DEV_FT5406;
+ }else if(strncmp(p,"ft6336",6)==0){
+ ft5x0x->id = FT6336;
+ ft5x0x->name = DEV_FT6336;
+ }else if(strncmp(p,"ft5206",6)==0){
+ ft5x0x->id = FT5206;
+ ft5x0x->name = DEV_FT5206;
+ }else if(strncmp(p,"ft5606",6)==0){
+ ft5x0x->id = FT5606;
+ ft5x0x->name = DEV_FT5606;
+ }else if(strncmp(p,"ft5306",6)==0){
+ ft5x0x->id = FT5306;
+ ft5x0x->name = DEV_FT5306;
+ }else if(strncmp(p,"ft5302",6)==0){
+ ft5x0x->id = FT5302;
+ ft5x0x->name = DEV_FT5302;
+ }else if(strncmp(p,"ft5",3)==0)
+ {
+ ft5x0x->id = FT5X0X;
+ ft5x0x->name = DEV_FT5X0X;
+ }else{
+ printk("FT5x0x touch disabled.\n");
+ return -ENODEV;
+ }
+
+ s = strchr(p,':');
+ strncpy(ft5x0x->cfg_name, p, s-p);
+
+ p = s + 1;
+ sscanf(p,"%d:%d:%d:%d:%d:%d:%d:%d:%x", &ft5x0x->irqgpio, &ft5x0x->reslx, &ft5x0x->resly, &ft5x0x->rstgpio, &ft5x0x->swap, &ft5x0x->xch, &ft5x0x->ych, &ft5x0x->nt, &ft5x0x->addr);
+
+ ft5x0x->irq = IRQ_GPIO;
+ printk("%s irqgpio=%d, reslx=%d, resly=%d, rstgpio=%d, swap=%d, xch=%d, ych=%d, nt=%d, addr=%x\n", ft5x0x->name, ft5x0x->irqgpio, ft5x0x->reslx, ft5x0x->resly, ft5x0x->rstgpio, ft5x0x->swap, ft5x0x->xch, ft5x0x->ych, ft5x0x->nt, ft5x0x->addr);
+
+ memset(retval,0x00,sizeof(retval));
+ ret = wmt_getsyspara("wmt.io.ts.upg", retval, &len);
+ if(!ret){
+ ft5x0x->upg = 1;
+ strncpy(ft5x0x->fw_name, retval, sizeof(ft5x0x->fw_name));
+ }
+
+#ifdef TOUCH_KEY
+ memset(retval,0x00,sizeof(retval));
+ ret = wmt_getsyspara("wmt.io.tskey", retval, &len);
+ if(!ret){
+ sscanf(retval,"%d:", &ft5x0x->nkeys);
+ p = strchr(retval,':');
+ p++;
+ for(i=0; i < ft5x0x->nkeys; i++ ){
+ sscanf(p,"%d:%d", &ft5x0x->tkey.ypos[i].y_lower, &ft5x0x->tkey.ypos[i].y_upper);
+ p = strchr(p,':');
+ p++;
+ p = strchr(p,':');
+ p++;
+ }
+ sscanf(p,"%d:%d:%d", &ft5x0x->tkey.axis, &ft5x0x->tkey.x_lower, &ft5x0x->tkey.x_upper);
+ ft5x0x->tskey_used = 1;
+ }
+#endif
+ return 0;
+}
+
+struct i2c_board_info ts_i2c_board_info = {
+ .type = TS_I2C_NAME,
+ .flags = 0x00,
+ .addr = FT5406_I2C_ADDR,
+ .platform_data = NULL,
+ .archdata = NULL,
+ .irq = -1,
+};
+
+static int ts_i2c_register_device (void)
+{
+ struct i2c_board_info *ts_i2c_bi;
+ struct i2c_adapter *adapter = NULL;
+ //struct i2c_client *client = NULL;
+
+ //ts_i2c_board_info.addr = FT5406_I2C_ADDR;
+ ts_i2c_bi = &ts_i2c_board_info;
+ adapter = i2c_get_adapter(FT5X0X_I2C_BUS);/*in bus 1*/
+
+ if (NULL == adapter) {
+ printk("can not get i2c adapter, client address error\n");
+ return -1;
+ }
+ l_client = i2c_new_device(adapter, ts_i2c_bi);
+ if (l_client == NULL) {
+ printk("allocate i2c client failed\n");
+ return -1;
+ }
+ i2c_put_adapter(adapter);
+ return 0;
+}
+
+static void ts_i2c_unregister_device(void)
+{
+ if (l_client != NULL)
+ {
+ i2c_unregister_device(l_client);
+ l_client = NULL;
+ }
+}
+
+static int __init ft5x0x_init(void)
+{
+ int ret = -ENOMEM;
+ struct ft5x0x_data *ft5x0x=NULL;
+
+ if (ts_i2c_register_device()<0)
+ {
+ dbg("Error to run ts_i2c_register_device()!\n");
+ return -1;
+ }
+
+ ft5x0x = kzalloc(sizeof(struct ft5x0x_data), GFP_KERNEL);
+ if(!ft5x0x){
+ dbg_err("mem alloc failed.\n");
+ return -ENOMEM;
+ }
+
+ pContext = ft5x0x;
+ ret = check_touch_env(ft5x0x);
+ if(ret < 0)
+ goto exit_free_mem;
+
+ ret = gpio_request(ft5x0x->irqgpio, "ts_irq");
+ if (ret < 0) {
+ printk("gpio(%d) touchscreen irq request fail\n", ft5x0x->irqgpio);
+ goto exit_free_mem;
+ }
+ wmt_gpio_setpull(ft5x0x->irqgpio, WMT_GPIO_PULL_UP);
+ gpio_direction_input(ft5x0x->irqgpio);
+
+ ret = gpio_request(ft5x0x->rstgpio, "ts_rst");
+ if (ret < 0) {
+ printk("gpio(%d) touchscreen reset request fail\n", ft5x0x->rstgpio);
+ goto exit_free_irqgpio;
+ }
+ gpio_direction_output(ft5x0x->rstgpio, 1);
+
+
+ ret = platform_device_register(&ft5x0x_device);
+ if(ret){
+ dbg_err("register platform drivver failed!\n");
+ goto exit_free_gpio;
+ }
+ platform_set_drvdata(&ft5x0x_device, ft5x0x);
+
+ ret = platform_driver_register(&ft5x0x_driver);
+ if(ret){
+ dbg_err("register platform device failed!\n");
+ goto exit_unregister_pdev;
+ }
+
+ return ret;
+
+exit_unregister_pdev:
+ platform_device_unregister(&ft5x0x_device);
+exit_free_gpio:
+ gpio_free(ft5x0x->rstgpio);
+exit_free_irqgpio:
+ gpio_free(ft5x0x->irqgpio);
+exit_free_mem:
+ kfree(ft5x0x);
+ pContext = NULL;
+ return ret;
+}
+
+static void ft5x0x_exit(void)
+{
+ if(!pContext) return;
+
+ gpio_free(pContext->rstgpio);
+ gpio_free(pContext->irqgpio);
+ platform_driver_unregister(&ft5x0x_driver);
+ platform_device_unregister(&ft5x0x_device);
+ kfree(pContext);
+ ts_i2c_unregister_device();
+ return;
+}
+
+late_initcall(ft5x0x_init);
+module_exit(ft5x0x_exit);
+module_param (ft5x0x_debug, byte, 0644);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("FocalTech.Touch");
diff --git a/drivers/input/touchscreen/ft6x0x/ft5x0x.h b/drivers/input/touchscreen/ft6x0x/ft5x0x.h
new file mode 100755
index 00000000..417af1f5
--- /dev/null
+++ b/drivers/input/touchscreen/ft6x0x/ft5x0x.h
@@ -0,0 +1,205 @@
+#ifndef __LINUX_FT5X0X_TS_H__
+#define __LINUX_FT5X0X_TS_H__
+
+#define DEV_FT5206 "touch_ft5206"
+#define DEV_FT5301 "touch_ft5301"
+#define DEV_FT5302 "touch_ft5302"
+#define DEV_FT5306 "touch_ft5306"
+#define DEV_FT5406 "touch_ft5406"
+#define DEV_FT5606 "touch_ft5606"
+#define DEV_FT6336 "touch_ft6336"
+
+
+#define DEV_FT5X0X "touch_ft5x0x"
+#define TS_I2C_NAME "ft5x0x-ts"
+#define FT5406_I2C_ADDR 0x38
+#define FT5X0X_I2C_BUS 0x01
+
+enum FT5X0X_ID{
+ FT5206 =1,
+ FT5301,
+ FT5302,
+ FT5306,
+ FT5406,
+ FT5606,
+ FT6336,
+ FT5X0X,
+};
+
+struct vt1603_ts_cal_info {
+ int a1;
+ int b1;
+ int c1;
+ int a2;
+ int b2;
+ int c2;
+ int delta;
+};
+
+#define SUPPORT_POINT_NUM 5//10
+struct ts_event {
+ int x[SUPPORT_POINT_NUM];
+ int y[SUPPORT_POINT_NUM];
+ int tid[SUPPORT_POINT_NUM];
+ int tpoint;
+};
+
+#define TOUCH_KEY
+
+#ifdef TOUCH_KEY
+#define NUM_KEYS 4
+struct key_pos{
+ int y_lower;
+ int y_upper;
+};
+
+struct ts_key{
+ int axis;
+ int x_lower;
+ int x_upper;
+ struct key_pos ypos[NUM_KEYS];
+};
+#endif
+
+struct ft5x0x_data {
+ int id;
+ unsigned int addr;
+ const char *name;
+ u8 fw_name[64];
+ u8 cfg_name[32];
+
+ struct i2c_client *client;
+ struct input_dev *input_dev;
+ struct ts_event event;
+ struct work_struct read_work;
+ struct workqueue_struct *workqueue;
+ struct mutex ts_mutex;
+ struct kobject *kobj;
+ #ifdef CONFIG_HAS_EARLYSUSPEND
+ struct early_suspend early_suspend;
+#endif
+ int earlysus;
+
+ int reslx;
+ int resly;
+
+ int tw;
+ int th;
+
+ int irq;
+ int irqgpio;
+ int rstgpio;
+/*
+ int igp_idx;
+ int igp_bit;
+
+ int rgp_idx;
+ int rgp_bit;
+*/
+
+ int nt;
+ int nb;
+ int xch;
+ int ych;
+ int swap;
+
+ int upg;
+ int load_cfg;
+ int dbg;
+#ifdef TOUCH_KEY
+ int tskey_used;
+ int tkey_pressed;
+ int nkeys;
+ int tkey_idx;
+ struct ts_key tkey;
+#endif
+
+};
+
+enum ft5x0x_ts_regs {
+ FT5X0X_REG_THGROUP = 0x80, /* touch threshold, related to sensitivity */
+ FT5X0X_REG_THPEAK = 0x81,
+ FT5X0X_REG_THCAL = 0x82,
+ FT5X0X_REG_THWATER = 0x83,
+ FT5X0X_REG_THTEMP = 0x84,
+ FT5X0X_REG_THDIFF = 0x85,
+ FT5X0X_REG_CTRL = 0x86,
+ FT5X0X_REG_TIMEENTERMONITOR = 0x87,
+ FT5X0X_REG_PERIODACTIVE = 0x88, /* report rate */
+ FT5X0X_REG_PERIODMONITOR = 0x89,
+ FT5X0X_REG_HEIGHT_B = 0x8a,
+ FT5X0X_REG_MAX_FRAME = 0x8b,
+ FT5X0X_REG_DIST_MOVE = 0x8c,
+ FT5X0X_REG_DIST_POINT = 0x8d,
+ FT5X0X_REG_FEG_FRAME = 0x8e,
+ FT5X0X_REG_SINGLE_CLICK_OFFSET = 0x8f,
+ FT5X0X_REG_DOUBLE_CLICK_TIME_MIN = 0x90,
+ FT5X0X_REG_SINGLE_CLICK_TIME = 0x91,
+ FT5X0X_REG_LEFT_RIGHT_OFFSET = 0x92,
+ FT5X0X_REG_UP_DOWN_OFFSET = 0x93,
+ FT5X0X_REG_DISTANCE_LEFT_RIGHT = 0x94,
+ FT5X0X_REG_DISTANCE_UP_DOWN = 0x95,
+ FT5X0X_REG_ZOOM_DIS_SQR = 0x96,
+ FT5X0X_REG_RADIAN_VALUE =0x97,
+ FT5X0X_REG_MAX_X_HIGH = 0x98,
+ FT5X0X_REG_MAX_X_LOW = 0x99,
+ FT5X0X_REG_MAX_Y_HIGH = 0x9a,
+ FT5X0X_REG_MAX_Y_LOW = 0x9b,
+ FT5X0X_REG_K_X_HIGH = 0x9c,
+ FT5X0X_REG_K_X_LOW = 0x9d,
+ FT5X0X_REG_K_Y_HIGH = 0x9e,
+ FT5X0X_REG_K_Y_LOW = 0x9f,
+ FT5X0X_REG_AUTO_CLB_MODE = 0xa0,
+ FT5X0X_REG_LIB_VERSION_H = 0xa1,
+ FT5X0X_REG_LIB_VERSION_L = 0xa2,
+ FT5X0X_REG_CIPHER = 0xa3,
+ FT5X0X_REG_MODE = 0xa4,
+ FT5X0X_REG_PMODE = 0xa5, /* Power Consume Mode */
+ FT5X0X_REG_FIRMID = 0xa6, /* Firmware version */
+ FT5X0X_REG_STATE = 0xa7,
+ FT5X0X_REG_FT5201ID = 0xa8,
+ FT5X0X_REG_ERR = 0xa9,
+ FT5X0X_REG_CLB = 0xaa,
+};
+
+//FT5X0X_REG_PMODE
+#define PMODE_ACTIVE 0x00
+#define PMODE_MONITOR 0x01
+#define PMODE_STANDBY 0x02
+#define PMODE_HIBERNATE 0x03
+
+#define DEV_NAME "wmtts"
+#define DEV_MAJOR 11
+
+#define TS_IOC_MAGIC 't'
+#define TS_IOCTL_CAL_START _IO(TS_IOC_MAGIC, 1)
+#define TS_IOCTL_CAL_DONE _IOW(TS_IOC_MAGIC, 2, int*)
+#define TS_IOCTL_GET_RAWDATA _IOR(TS_IOC_MAGIC, 3, int*)
+#define TS_IOCTL_CAL_QUIT _IOW(TS_IOC_MAGIC, 4, int*)
+#define TS_IOCTL_CAL_CAP _IOW(TS_IOC_MAGIC, 5, int*)
+#define TS_IOC_MAXNR 5
+
+extern int wmt_setsyspara(char *varname, unsigned char *varval);
+extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen);
+extern int wmt_i2c_xfer_continue_if_4(struct i2c_msg *msg, unsigned int num,int bus_id);
+
+//#define FT_DEBUG
+
+#undef dbg
+#ifdef FT_DEBUG
+ #define dbg(fmt,args...) printk("DBG:%s_%d:"fmt,__FUNCTION__,__LINE__,##args)
+#else
+ #define dbg(fmt,args...)
+#endif
+
+#undef dbg_err
+#define dbg_err(fmt,args...) printk("ERR:%s_%d:"fmt,__FUNCTION__,__LINE__,##args)
+
+//#define FTS_DBG
+#ifdef FTS_DBG
+#define DBG(fmt, args...) printk("[FTS]" fmt, ## args)
+#else
+#define DBG(fmt, args...) do{}while(0)
+#endif
+
+#endif
diff --git a/drivers/input/touchscreen/ft6x0x/ft5x0x_upg.c b/drivers/input/touchscreen/ft6x0x/ft5x0x_upg.c
new file mode 100755
index 00000000..9db72130
--- /dev/null
+++ b/drivers/input/touchscreen/ft6x0x/ft5x0x_upg.c
@@ -0,0 +1,506 @@
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/mount.h>
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+#include <linux/syscalls.h>
+#include <asm/unistd.h>
+#include <asm/uaccess.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include "ft5x0x.h"
+
+typedef enum
+{
+ ERR_OK,
+ ERR_MODE,
+ ERR_READID,
+ ERR_ERASE,
+ ERR_STATUS,
+ ERR_ECC,
+ ERR_DL_ERASE_FAIL,
+ ERR_DL_PROGRAM_FAIL,
+ ERR_DL_VERIFY_FAIL,
+ ERR_FMID
+}E_UPGRADE_ERR_TYPE;
+
+#define FT5X_CTPM_ID_L 0X79
+#define FT5X_CTPM_ID_H 0X03
+
+#define FT56_CTPM_ID_L 0X79
+#define FT56_CTPM_ID_H 0X06
+
+#define FTS_PACKET_LENGTH 128
+
+extern struct ft5x0x_data *pContext;
+extern int ft5x0x_i2c_rxdata(char *rxdata, int length);
+extern int ft5x0x_i2c_txdata(char *txdata, int length);
+
+static int ft5x0x_write_reg(u8 addr, u8 para)
+{
+ u8 buf[2];
+ int ret = -1;
+
+ buf[0] = addr;
+ buf[1] = para;
+ ret = ft5x0x_i2c_txdata(buf, 2);
+ if (ret <= 0) {
+ printk("write reg failed! %x ret: %d", buf[0], ret);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int ft5x0x_read_reg(u8 addr, u8 *pdata)
+{
+ int ret;
+ u8 buf[2];
+ struct i2c_msg msgs[2];
+
+ //
+ buf[0] = addr; //register address
+
+ msgs[0].addr = pContext->addr;
+ msgs[0].flags = 0 | I2C_M_NOSTART;
+ msgs[0].len = 1;
+ msgs[0].buf = buf;
+
+ msgs[1].addr = pContext->addr;
+ msgs[1].flags = I2C_M_RD;
+ msgs[1].len = 1;
+ msgs[1].buf = pdata;
+
+ //ret = wmt_i2c_xfer_continue_if_4(msgs, 2, FT5X0X_I2C_BUS);
+ ret = i2c_transfer(pContext->client->adapter, msgs, 2);
+ if (ret <= 0)
+ printk("msg %s i2c read error: %d\n", __func__, ret);
+
+ return ret;
+
+}
+
+
+/*
+[function]:
+ send a command to ctpm.
+[parameters]:
+ btcmd[in] :command code;
+ btPara1[in] :parameter 1;
+ btPara2[in] :parameter 2;
+ btPara3[in] :parameter 3;
+ num[in] :the valid input parameter numbers, if only command code needed and no parameters followed,then the num is 1;
+[return]:
+ FTS_TRUE :success;
+ FTS_FALSE :io fail;
+*/
+static u8 cmd_write(u8 *cmd,u8 num)
+{
+ return ft5x0x_i2c_txdata(cmd, num);
+}
+
+/*
+[function]:
+ write data to ctpm , the destination address is 0.
+[parameters]:
+ pbt_buf[in] :point to data buffer;
+ bt_len[in] :the data numbers;
+[return]:
+ FTS_TRUE :success;
+ FTS_FALSE :io fail;
+*/
+static u8 byte_write(u8* pbt_buf, int dw_len)
+{
+
+ return ft5x0x_i2c_txdata( pbt_buf, dw_len);
+}
+
+/*
+[function]:
+ read out data from ctpm,the destination address is 0.
+[parameters]:
+ pbt_buf[out] :point to data buffer;
+ bt_len[in] :the data numbers;
+[return]:
+ FTS_TRUE :success;
+ FTS_FALSE :io fail;
+*/
+static u8 byte_read(u8* pbt_buf, u8 bt_len)
+{
+ int ret;
+ struct i2c_msg msg[1];
+
+ msg[0].addr = pContext->addr;
+ msg[0].flags = I2C_M_RD;
+ msg[0].len = bt_len;
+ msg[0].buf = pbt_buf;
+
+ ret = i2c_transfer(pContext->client->adapter, msg, 1);
+ //ret = wmt_i2c_xfer_continue_if_4(msg, 1, FT5X0X_I2C_BUS);
+ if (ret <= 0)
+ printk("msg i2c read error: %d\n", ret);
+
+ return ret;
+}
+
+
+/*
+[function]:
+ burn the FW to ctpm.
+[parameters]:(ref. SPEC)
+ pbt_buf[in] :point to Head+FW ;
+ dw_lenth[in]:the length of the FW + 6(the Head length);
+ bt_ecc[in] :the ECC of the FW
+[return]:
+ ERR_OK :no error;
+ ERR_MODE :fail to switch to UPDATE mode;
+ ERR_READID :read id fail;
+ ERR_ERASE :erase chip fail;
+ ERR_STATUS :status error;
+ ERR_ECC :ecc error.
+*/
+static E_UPGRADE_ERR_TYPE ft5x0x_fw_upgrade(struct ft5x0x_data *ft5x0x, u8* pbt_buf, int dw_lenth)
+{
+ int i = 0,j = 0,i_ret;
+ int packet_number;
+ int temp,lenght;
+ u8 packet_buf[FTS_PACKET_LENGTH + 6];
+ u8 auc_i2c_write_buf[10];
+ u8 reg_val[2] = {0};
+ u8 ctpm_id[2] = {0};
+ u8 cmd[4];
+ u8 bt_ecc;
+
+ /*********Step 1:Reset CTPM *****/
+ /*write 0xaa to register 0xfc*/
+ ft5x0x_write_reg(0xfc,0xaa);
+ msleep(50);
+ /*write 0x55 to register 0xfc*/
+ ft5x0x_write_reg(0xfc,0x55);
+ printk("[FTS] Step 1: Reset CTPM.\n");
+ msleep(30);
+
+ /*********Step 2:Enter upgrade mode *****/
+ auc_i2c_write_buf[0] = 0x55;
+ auc_i2c_write_buf[1] = 0xaa;
+ do{
+ i ++;
+ i_ret = byte_write(auc_i2c_write_buf, 2);
+ mdelay(5);
+ }while(i_ret <= 0 && i < 5 );
+ msleep(20);
+
+ /*********Step 3:check READ-ID**********/
+ if(ft5x0x->id == FT5606){
+ ctpm_id[0] = FT56_CTPM_ID_L;
+ ctpm_id[1] = FT56_CTPM_ID_H;
+ }else{
+ ctpm_id[0] = FT5X_CTPM_ID_L;
+ ctpm_id[1] = FT5X_CTPM_ID_H;
+ }
+
+ cmd[0] = 0x90;
+ cmd[1] = 0x00;
+ cmd[2] = 0x00;
+ cmd[3] = 0x00;
+ cmd_write(cmd,4);
+ byte_read(reg_val,2);
+ if (reg_val[0] == ctpm_id[0] && reg_val[1] == ctpm_id[1]){
+ printk("[FTS] Step 3: CTPM ID,ID1 = 0x%x,ID2 = 0x%x\n",reg_val[0],reg_val[1]);
+ }else{
+ printk("[FTS] ID_ERROR: CTPM ID,ID1 = 0x%x,ID2 = 0x%x\n",reg_val[0],reg_val[1]);
+ return ERR_READID;
+ }
+
+ cmd[0] = 0xcd;
+ cmd_write(cmd,1);
+ byte_read(reg_val,1);
+ printk("[FTS] bootloader version = 0x%x\n", reg_val[0]);
+
+ /******Step 4:erase app and panel paramenter area *********/
+ cmd[0] = 0x61;
+ cmd_write(cmd,1); //erase app area
+ msleep(1500);
+ cmd[0] = 0x63;
+ cmd_write(cmd,1); //erase panel parameter area
+ msleep(100);
+ printk("[FTS] Step 4: erase. \n");
+
+ /*********Step 5:write firmware(FW) to ctpm flash*********/
+ bt_ecc = 0;
+ printk("[FTS] Step 5: start upgrade. \n");
+ dw_lenth = dw_lenth - 8;
+ packet_number = (dw_lenth) / FTS_PACKET_LENGTH;
+ packet_buf[0] = 0xbf;
+ packet_buf[1] = 0x00;
+ for (j=0;j<packet_number;j++){
+ temp = j * FTS_PACKET_LENGTH;
+ packet_buf[2] = (u8)(temp>>8);
+ packet_buf[3] = (u8)temp;
+ lenght = FTS_PACKET_LENGTH;
+ packet_buf[4] = (u8)(lenght>>8);
+ packet_buf[5] = (u8)lenght;
+
+ for (i=0;i<FTS_PACKET_LENGTH;i++){
+ packet_buf[6+i] = pbt_buf[j*FTS_PACKET_LENGTH + i];
+ bt_ecc ^= packet_buf[6+i];
+ }
+
+ byte_write(&packet_buf[0],FTS_PACKET_LENGTH + 6);
+ mdelay(FTS_PACKET_LENGTH/6 + 1);
+ if ((j * FTS_PACKET_LENGTH % 1024) == 0){
+ printk("[FTS] upgrade the 0x%x th byte.\n", ((unsigned int)j) * FTS_PACKET_LENGTH);
+ }
+ }
+
+ if ((dw_lenth) % FTS_PACKET_LENGTH > 0){
+ temp = packet_number * FTS_PACKET_LENGTH;
+ packet_buf[2] = (u8)(temp>>8);
+ packet_buf[3] = (u8)temp;
+
+ temp = (dw_lenth) % FTS_PACKET_LENGTH;
+ packet_buf[4] = (u8)(temp>>8);
+ packet_buf[5] = (u8)temp;
+
+ for (i=0;i<temp;i++){
+ packet_buf[6+i] = pbt_buf[ packet_number*FTS_PACKET_LENGTH + i];
+ bt_ecc ^= packet_buf[6+i];
+ }
+
+ byte_write(&packet_buf[0],temp+6);
+ mdelay(20);
+ }
+
+ //send the last six byte
+ for (i = 0; i<6; i++){
+ temp = 0x6ffa + i;
+ packet_buf[2] = (u8)(temp>>8);
+ packet_buf[3] = (u8)temp;
+ temp =1;
+ packet_buf[4] = (u8)(temp>>8);
+ packet_buf[5] = (u8)temp;
+ packet_buf[6] = pbt_buf[ dw_lenth + i];
+ bt_ecc ^= packet_buf[6];
+
+ byte_write(&packet_buf[0],7);
+ mdelay(20);
+ }
+
+ /*********Step 6: read out checksum********************/
+ /*send the opration head*/
+ cmd[0] = 0xcc;
+ cmd_write(cmd,1);
+ byte_read(reg_val,1);
+ printk("[FTS] Step 6:read ECC 0x%x, firmware ECC 0x%x. \n", reg_val[0], bt_ecc);
+ if(reg_val[0] != bt_ecc){
+ return ERR_ECC;
+ }
+
+ /*********Step 7: reset the new FW***********************/
+ cmd[0] = 0x07;
+ cmd_write(cmd,1);
+
+ msleep(300); //make sure CTP startup normally
+
+ return ERR_OK;
+}
+
+int ft5x0x_auto_clb(void)
+{
+ u8 uc_temp;
+ u8 i ;
+
+ printk("[FTS] start auto CLB.\n");
+ msleep(200);
+ ft5x0x_write_reg(0, 0x40);
+ msleep(100); //make sure already enter factory mode
+ ft5x0x_write_reg(2, 0x4); //write command to start calibration
+ msleep(300);
+ for(i=0;i<100;i++){
+ ft5x0x_read_reg(0,&uc_temp);
+ if ( ((uc_temp&0x70)>>4) == 0x0){ //return to normal mode, calibration finish
+ break;
+ }
+ msleep(200);
+ printk("[FTS] waiting calibration %d\n",i);
+ }
+ printk("[FTS] calibration OK.\n");
+
+ msleep(300);
+ ft5x0x_write_reg(0, 0x40); //goto factory mode
+ msleep(100); //make sure already enter factory mode
+ ft5x0x_write_reg(2, 0x5); //store CLB result
+ msleep(300);
+ ft5x0x_write_reg(0, 0x0); //return to normal mode
+ msleep(300);
+ printk("[FTS] store CLB result OK.\n");
+ return 0;
+}
+
+static int ft5x0x_get_bin_ver(const u8 *fw, int fw_szie)
+{
+ if (fw_szie > 2){
+ return fw[fw_szie - 2];
+ }else{
+ return 0xff; //default value
+ }
+ return 0xff;
+}
+
+int ft5x0x_read_fw_ver(void)
+{
+ u8 ver=0;
+ int ret=0;
+
+ ret = ft5x0x_read_reg(FT5X0X_REG_FIRMID, &ver);
+ if(ret > 0)
+ return ver;
+
+ return ret;
+}
+
+
+static int ft5x0x_get_fw_szie(const char *fw_name)
+{
+ struct file *pfile = NULL;
+ struct inode *inode;
+ unsigned long magic;
+ off_t fsize = 0;
+
+ if(fw_name == NULL){
+ dbg_err("Firmware name error.\n");
+ return -EFAULT;
+ }
+
+ if (NULL == pfile)
+ pfile = filp_open(fw_name, O_RDONLY, 0);
+
+ if (IS_ERR(pfile)) {
+ dbg_err("File open error: %s.\n", fw_name);
+ return -EIO;
+ }
+
+ inode = pfile->f_dentry->d_inode;
+ magic = inode->i_sb->s_magic;
+ fsize = inode->i_size;
+ filp_close(pfile, NULL);
+ return fsize;
+}
+
+static int ft5x0x_read_fw(const char *fw_name, u8 *buf)
+{
+ struct file *pfile = NULL;
+ struct inode *inode;
+ unsigned long magic;
+ off_t fsize;
+ loff_t pos;
+ mm_segment_t fs;
+
+ if(fw_name == NULL){
+ dbg_err("Firmware name error.\n");
+ return -EFAULT;
+ }
+
+ if (NULL == pfile)
+ pfile = filp_open(fw_name, O_RDONLY, 0);
+ if (IS_ERR(pfile)) {
+ dbg_err("File open error: %s.\n", fw_name);
+ return -EIO;
+ }
+
+ inode = pfile->f_dentry->d_inode;
+ magic = inode->i_sb->s_magic;
+ fsize = inode->i_size;
+ fs = get_fs();
+ set_fs(KERNEL_DS);
+ pos = 0;
+ vfs_read(pfile, buf, fsize, &pos);
+ filp_close(pfile, NULL);
+ set_fs(fs);
+
+ return 0;
+}
+
+#define FW_SUFFFIX ".bin"
+#define SD_UPG_BIN_PATH "/sdcard/_wmt_ft5x0x_fw_app.bin"
+#define FS_UPG_BIN_PATH "/lib/firmware/"
+
+int ft5x0x_upg_fw_bin(struct ft5x0x_data *ft5x0x, int check_ver)
+{
+ int i_ret = 0;
+ int fwsize = 0;
+ int hw_fw_ver;
+ int bin_fw_ver;
+ int do_upg;
+ u8 *pbt_buf = NULL;
+ u8 fw_path[128] = {0};
+
+ if(ft5x0x->upg)
+ sprintf(fw_path,"%s%s%s", FS_UPG_BIN_PATH, ft5x0x->fw_name,FW_SUFFFIX);//get fw binary file from filesystem
+ else
+ strcpy(fw_path,SD_UPG_BIN_PATH); //get fw binary file from SD card
+
+ fwsize = ft5x0x_get_fw_szie(fw_path);
+ if (fwsize <= 0) {
+ dbg_err("Get firmware size failed\n");
+ return -EIO;
+ }
+
+ if (fwsize < 8 || fwsize > 32 * 1024) {
+ dbg_err("FW length error\n");
+ return -EIO;
+ }
+
+ pbt_buf = kmalloc(fwsize + 1, GFP_KERNEL);
+ if (ft5x0x_read_fw(fw_path, pbt_buf)) {
+ dbg_err("Request_firmware failed\n");
+ i_ret = -EIO;
+ goto exit;
+ }
+
+ hw_fw_ver =ft5x0x_read_fw_ver();
+ if(hw_fw_ver <= 0){
+ dbg_err("Read firmware version failed\n");
+ i_ret = hw_fw_ver;
+ goto exit;
+ }
+
+ bin_fw_ver = ft5x0x_get_bin_ver(pbt_buf, fwsize);
+ printk("[FTS] hardware fw ver 0x%0x, binary ver 0x%0x\n",hw_fw_ver, bin_fw_ver);
+
+ if(check_ver){
+ if(hw_fw_ver == 0xa6 || hw_fw_ver < bin_fw_ver)
+ do_upg = 1;
+ else
+ do_upg = 0;
+ }else{
+ do_upg = 1;
+ }
+
+ if(do_upg){
+ if ((pbt_buf[fwsize - 8] ^ pbt_buf[fwsize - 6]) == 0xFF &&
+ (pbt_buf[fwsize - 7] ^ pbt_buf[fwsize - 5]) == 0xFF &&
+ (pbt_buf[fwsize - 3] ^ pbt_buf[fwsize - 4]) == 0xFF) {
+ i_ret = ft5x0x_fw_upgrade(ft5x0x, pbt_buf, fwsize);
+ if (i_ret)
+ dbg_err("Upgrade failed, i_ret=%d\n",i_ret);
+ else {
+ hw_fw_ver = ft5x0x_read_fw_ver();
+ printk("[FTS] upgrade to new version 0x%x\n", hw_fw_ver);
+ }
+ } else {
+ dbg_err("FW format error\n");
+ }
+ }
+
+ ft5x0x_auto_clb();/*start auto CLB*/
+
+exit:
+ kfree(pbt_buf);
+ return i_ret;
+}
+
+
diff --git a/drivers/input/touchscreen/ft6x0x/ft6x06_ex_fun.c b/drivers/input/touchscreen/ft6x0x/ft6x06_ex_fun.c
new file mode 100755
index 00000000..08fc6069
--- /dev/null
+++ b/drivers/input/touchscreen/ft6x0x/ft6x06_ex_fun.c
@@ -0,0 +1,1021 @@
+/*
+ *drivers/input/touchscreen/ft5x06_ex_fun.c
+ *
+ *FocalTech ft6x06 expand function for debug.
+ *
+ *Copyright (c) 2010 Focal tech Ltd.
+ *
+ *This software is licensed under the terms of the GNU General Public
+ *License version 2, as published by the Free Software Foundation, and
+ *may be copied, distributed, and modified under those terms.
+ *
+ *This program is distributed in the hope that it will be useful,
+ *but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *GNU General Public License for more details.
+ *
+ *Note:the error code of EIO is the general error in this file.
+ */
+
+
+#include "ft6x06_ex_fun.h"
+#include "ft6x06_ts.h"
+
+#include <linux/mount.h>
+#include <linux/netdevice.h>
+#include <linux/proc_fs.h>
+
+struct Upgrade_Info {
+ u16 delay_aa; /*delay of write FT_UPGRADE_AA */
+ u16 delay_55; /*delay of write FT_UPGRADE_55 */
+ u8 upgrade_id_1; /*upgrade id 1 */
+ u8 upgrade_id_2; /*upgrade id 2 */
+ u16 delay_readid; /*delay of read id */
+ u16 delay_earse_flash; /*delay of earse flash*/
+};
+
+
+int fts_ctpm_fw_upgrade(struct i2c_client *client, u8 *pbt_buf,
+ u32 dw_lenth);
+
+static unsigned char CTPM_FW[] = {
+ #include "FT5406.i"
+};
+
+static struct mutex g_device_mutex;
+
+int ft6x06_write_reg(struct i2c_client *client, u8 regaddr, u8 regvalue)
+{
+ unsigned char buf[2] = {0};
+ buf[0] = regaddr;
+ buf[1] = regvalue;
+
+ return ft6x06_i2c_Write(client, buf, sizeof(buf));
+}
+
+
+int ft6x06_read_reg(struct i2c_client *client, u8 regaddr, u8 *regvalue)
+{
+ return ft6x06_i2c_Read(client, &regaddr, 1, regvalue, 1);
+}
+
+
+int fts_ctpm_auto_clb(struct i2c_client *client)
+{
+ unsigned char uc_temp = 0x00;
+ unsigned char i = 0;
+
+ /*start auto CLB */
+ msleep(200);
+
+ ft6x06_write_reg(client, 0, FTS_FACTORYMODE_VALUE);
+ /*make sure already enter factory mode */
+ msleep(100);
+ /*write command to start calibration */
+ ft6x06_write_reg(client, 2, 0x4);
+ msleep(300);
+ for (i = 0; i < 100; i++) {
+ ft6x06_read_reg(client, 0, &uc_temp);
+ /*return to normal mode, calibration finish */
+ if (0x0 == ((uc_temp & 0x70) >> 4))
+ break;
+ }
+
+ msleep(200);
+ /*calibration OK */
+ msleep(300);
+ ft6x06_write_reg(client, 0, FTS_FACTORYMODE_VALUE); /*goto factory mode for store */
+ msleep(100); /*make sure already enter factory mode */
+ ft6x06_write_reg(client, 2, 0x5); /*store CLB result */
+ msleep(300);
+ ft6x06_write_reg(client, 0, FTS_WORKMODE_VALUE); /*return to normal mode */
+ msleep(300);
+
+ /*store CLB result OK */
+ return 0;
+}
+
+/*
+upgrade with *.i file
+*/
+int fts_ctpm_fw_upgrade_with_i_file(struct i2c_client *client)
+{
+ u8 *pbt_buf = NULL;
+ int i_ret;
+ int fw_len = sizeof(CTPM_FW);
+
+ /*judge the fw that will be upgraded
+ * if illegal, then stop upgrade and return.
+ */
+
+ if (fw_len < 8 || fw_len > 32 * 1024) {
+ dev_err(&client->dev, "%s:FW length error\n", __func__);
+ return -EIO;
+ }
+
+ /*FW upgrade */
+ pbt_buf = CTPM_FW;
+ /*call the upgrade function */
+
+ i_ret = fts_ctpm_fw_upgrade(client, pbt_buf, sizeof(CTPM_FW));
+ if (i_ret != 0)
+ dev_err(&client->dev, "%s:upgrade failed. err.\n",
+ __func__);
+
+ return i_ret;
+}
+
+u8 fts_ctpm_get_i_file_ver(void)
+{
+ u16 ui_sz;
+ ui_sz = sizeof(CTPM_FW);
+ if (ui_sz > 2)
+ return CTPM_FW[0x10a];
+
+ return 0x00; /*default value */
+}
+
+/*update project setting
+*only update these settings for COB project, or for some special case
+*/
+int fts_ctpm_update_project_setting(struct i2c_client *client)
+{
+ u8 uc_i2c_addr; /*I2C slave address (7 bit address)*/
+ u8 uc_io_voltage; /*IO Voltage 0---3.3v; 1----1.8v*/
+ u8 uc_panel_factory_id; /*TP panel factory ID*/
+ u8 buf[FTS_SETTING_BUF_LEN];
+ u8 reg_val[2] = {0};
+ u8 auc_i2c_write_buf[10] = {0};
+ u8 packet_buf[FTS_SETTING_BUF_LEN + 6];
+ u32 i = 0;
+ int i_ret;
+
+ uc_i2c_addr = client->addr;
+ uc_io_voltage = 0x0;
+ uc_panel_factory_id = 0x5a;
+
+
+ /*Step 1:Reset CTPM
+ *write 0xaa to register 0xfc
+ */
+ ft6x06_write_reg(client, 0xfc, 0xaa);
+ msleep(50);
+
+ /*write 0x55 to register 0xfc */
+ ft6x06_write_reg(client, 0xfc, 0x55);
+ msleep(30);
+
+ /*********Step 2:Enter upgrade mode *****/
+ auc_i2c_write_buf[0] = 0x55;
+ auc_i2c_write_buf[1] = 0xaa;
+ do {
+ i++;
+ i_ret = ft6x06_i2c_Write(client, auc_i2c_write_buf, 2);
+ msleep(5);
+ } while (i_ret <= 0 && i < 5);
+
+
+ /*********Step 3:check READ-ID***********************/
+ auc_i2c_write_buf[0] = 0x90;
+ auc_i2c_write_buf[1] = auc_i2c_write_buf[2] = auc_i2c_write_buf[3] =
+ 0x00;
+
+ ft6x06_i2c_Read(client, auc_i2c_write_buf, 4, reg_val, 2);
+
+ if (reg_val[0] == 0x79 && reg_val[1] == 0x3)
+ dev_dbg(&client->dev, "[FTS] Step 3: CTPM ID,ID1 = 0x%x,ID2 = 0x%x\n",
+ reg_val[0], reg_val[1]);
+ else
+ return -EIO;
+
+ auc_i2c_write_buf[0] = 0xcd;
+ ft6x06_i2c_Read(client, auc_i2c_write_buf, 1, reg_val, 1);
+ dev_dbg(&client->dev, "bootloader version = 0x%x\n", reg_val[0]);
+
+ /*--------- read current project setting ---------- */
+ /*set read start address */
+ buf[0] = 0x3;
+ buf[1] = 0x0;
+ buf[2] = 0x78;
+ buf[3] = 0x0;
+
+ ft6x06_i2c_Read(client, buf, 4, buf, FTS_SETTING_BUF_LEN);
+ dev_dbg(&client->dev, "[FTS] old setting: uc_i2c_addr = 0x%x,\
+ uc_io_voltage = %d, uc_panel_factory_id = 0x%x\n",
+ buf[0], buf[2], buf[4]);
+
+ /*--------- Step 4:erase project setting --------------*/
+ auc_i2c_write_buf[0] = 0x63;
+ ft6x06_i2c_Write(client, auc_i2c_write_buf, 1);
+ msleep(100);
+
+ /*---------- Set new settings ---------------*/
+ buf[0] = uc_i2c_addr;
+ buf[1] = ~uc_i2c_addr;
+ buf[2] = uc_io_voltage;
+ buf[3] = ~uc_io_voltage;
+ buf[4] = uc_panel_factory_id;
+ buf[5] = ~uc_panel_factory_id;
+ packet_buf[0] = 0xbf;
+ packet_buf[1] = 0x00;
+ packet_buf[2] = 0x78;
+ packet_buf[3] = 0x0;
+ packet_buf[4] = 0;
+ packet_buf[5] = FTS_SETTING_BUF_LEN;
+
+ for (i = 0; i < FTS_SETTING_BUF_LEN; i++)
+ packet_buf[6 + i] = buf[i];
+
+ ft6x06_i2c_Write(client, packet_buf, FTS_SETTING_BUF_LEN + 6);
+ msleep(100);
+
+ /********* reset the new FW***********************/
+ auc_i2c_write_buf[0] = 0x07;
+ ft6x06_i2c_Write(client, auc_i2c_write_buf, 1);
+
+ msleep(200);
+ return 0;
+}
+
+int fts_ctpm_auto_upgrade(struct i2c_client *client)
+{
+ u8 uc_host_fm_ver = FT6x06_REG_FW_VER;
+ u8 uc_tp_fm_ver;
+ int i_ret;
+
+ ft6x06_read_reg(client, FT6x06_REG_FW_VER, &uc_tp_fm_ver);
+ uc_host_fm_ver = fts_ctpm_get_i_file_ver();
+
+ if (/*the firmware in touch panel maybe corrupted */
+ uc_tp_fm_ver == FT6x06_REG_FW_VER ||
+ /*the firmware in host flash is new, need upgrade */
+ uc_tp_fm_ver < uc_host_fm_ver
+ ) {
+ msleep(100);
+ dev_dbg(&client->dev, "[FTS] uc_tp_fm_ver = 0x%x, uc_host_fm_ver = 0x%x\n",
+ uc_tp_fm_ver, uc_host_fm_ver);
+ i_ret = fts_ctpm_fw_upgrade_with_i_file(client);
+ if (i_ret == 0) {
+ msleep(300);
+ uc_host_fm_ver = fts_ctpm_get_i_file_ver();
+ dev_dbg(&client->dev, "[FTS] upgrade to new version 0x%x\n",
+ uc_host_fm_ver);
+ } else {
+ pr_err("[FTS] upgrade failed ret=%d.\n", i_ret);
+ return -EIO;
+ }
+ }
+
+ return 0;
+}
+
+void delay_qt_ms(unsigned long w_ms)
+{
+ unsigned long i;
+ unsigned long j;
+
+ for (i = 0; i < w_ms; i++)
+ {
+ for (j = 0; j < 1000; j++)
+ {
+ udelay(1);
+ }
+ }
+}
+
+int fts_ctpm_fw_upgrade(struct i2c_client *client, u8 *pbt_buf,
+ u32 dw_lenth)
+{
+ u8 reg_val[2] = {0};
+ u32 i = 0;
+ u32 packet_number;
+ u32 j;
+ u32 temp;
+ u32 lenght;
+ u32 fw_length;
+ u8 packet_buf[FTS_PACKET_LENGTH + 6];
+ u8 auc_i2c_write_buf[10];
+ u8 bt_ecc;
+ int i_ret;
+
+
+ if(pbt_buf[0] != 0x02)
+ {
+ DBG("[FTS] FW first byte is not 0x02. so it is invalid \n");
+ return -1;
+ }
+
+ if(dw_lenth > 0x11f)
+ {
+ fw_length = ((u32)pbt_buf[0x100]<<8) + pbt_buf[0x101];
+ if(dw_lenth < fw_length)
+ {
+ DBG("[FTS] Fw length is invalid \n");
+ return -1;
+ }
+ }
+ else
+ {
+ DBG("[FTS] Fw length is invalid \n");
+ return -1;
+ }
+
+ //DBG("[FTS] Step 3: CTPM ID,ID1 = 0x%x,ID2 = 0x%x\n", reg_val[0], reg_val[1]);
+
+ for (i = 0; i < FTS_UPGRADE_LOOP; i++) {
+ /*********Step 1:Reset CTPM *****/
+ /*write 0xaa to register 0xbc */
+
+ ft6x06_write_reg(client, 0xbc, FT_UPGRADE_AA);
+ msleep(FT6X06_UPGRADE_AA_DELAY);
+
+ /*write 0x55 to register 0xbc */
+ ft6x06_write_reg(client, 0xbc, FT_UPGRADE_55);
+
+ msleep(FT6X06_UPGRADE_55_DELAY);
+
+ /*********Step 2:Enter upgrade mode *****/
+ auc_i2c_write_buf[0] = FT_UPGRADE_55;
+ ft6x06_i2c_Write(client, auc_i2c_write_buf, 1);
+
+ auc_i2c_write_buf[0] = FT_UPGRADE_AA;
+ ft6x06_i2c_Write(client, auc_i2c_write_buf, 1);
+ msleep(FT6X06_UPGRADE_READID_DELAY);
+
+ /*********Step 3:check READ-ID***********************/
+ auc_i2c_write_buf[0] = 0x90;
+ auc_i2c_write_buf[1] = auc_i2c_write_buf[2] = auc_i2c_write_buf[3] =
+ 0x00;
+ reg_val[0] = 0x00;
+ reg_val[1] = 0x00;
+ ft6x06_i2c_Read(client, auc_i2c_write_buf, 4, reg_val, 2);
+
+
+ if (reg_val[0] == FT6X06_UPGRADE_ID_1
+ && reg_val[1] == FT6X06_UPGRADE_ID_2) {
+ //dev_dbg(&client->dev, "[FTS] Step 3: CTPM ID,ID1 = 0x%x,ID2 = 0x%x\n",
+ //reg_val[0], reg_val[1]);
+ DBG("[FTS] Step 3: GET CTPM ID OK,ID1 = 0x%x,ID2 = 0x%x\n",
+ reg_val[0], reg_val[1]);
+ break;
+ } else {
+ dev_err(&client->dev, "[FTS] Step 3: GET CTPM ID FAIL,ID1 = 0x%x,ID2 = 0x%x\n",
+ reg_val[0], reg_val[1]);
+ }
+ }
+ if (i >= FTS_UPGRADE_LOOP)
+ return -EIO;
+
+ auc_i2c_write_buf[0] = 0x90;
+ auc_i2c_write_buf[1] = 0x00;
+ auc_i2c_write_buf[2] = 0x00;
+ auc_i2c_write_buf[3] = 0x00;
+ auc_i2c_write_buf[4] = 0x00;
+ ft6x06_i2c_Write(client, auc_i2c_write_buf, 5);
+
+ //auc_i2c_write_buf[0] = 0xcd;
+ //ft6x06_i2c_Read(client, auc_i2c_write_buf, 1, reg_val, 1);
+
+
+ /*Step 4:erase app and panel paramenter area*/
+ DBG("Step 4:erase app and panel paramenter area\n");
+ auc_i2c_write_buf[0] = 0x61;
+ ft6x06_i2c_Write(client, auc_i2c_write_buf, 1); /*erase app area */
+ msleep(FT6X06_UPGRADE_EARSE_DELAY);
+
+ for(i = 0;i < 200;i++)
+ {
+ auc_i2c_write_buf[0] = 0x6a;
+ auc_i2c_write_buf[1] = 0x00;
+ auc_i2c_write_buf[2] = 0x00;
+ auc_i2c_write_buf[3] = 0x00;
+ reg_val[0] = 0x00;
+ reg_val[1] = 0x00;
+ ft6x06_i2c_Read(client, auc_i2c_write_buf, 4, reg_val, 2);
+ if(0xb0 == reg_val[0] && 0x02 == reg_val[1])
+ {
+ DBG("[FTS] erase app finished \n");
+ break;
+ }
+ msleep(50);
+ }
+
+ /*********Step 5:write firmware(FW) to ctpm flash*********/
+ bt_ecc = 0;
+ DBG("Step 5:write firmware(FW) to ctpm flash\n");
+
+ dw_lenth = fw_length;
+ packet_number = (dw_lenth) / FTS_PACKET_LENGTH;
+ packet_buf[0] = 0xbf;
+ packet_buf[1] = 0x00;
+
+ for (j = 0; j < packet_number; j++) {
+ temp = j * FTS_PACKET_LENGTH;
+ packet_buf[2] = (u8) (temp >> 8);
+ packet_buf[3] = (u8) temp;
+ lenght = FTS_PACKET_LENGTH;
+ packet_buf[4] = (u8) (lenght >> 8);
+ packet_buf[5] = (u8) lenght;
+
+ for (i = 0; i < FTS_PACKET_LENGTH; i++) {
+ packet_buf[6 + i] = pbt_buf[j * FTS_PACKET_LENGTH + i];
+ bt_ecc ^= packet_buf[6 + i];
+ }
+
+ ft6x06_i2c_Write(client, packet_buf, FTS_PACKET_LENGTH + 6);
+
+ for(i = 0;i < 30;i++)
+ {
+ auc_i2c_write_buf[0] = 0x6a;
+ auc_i2c_write_buf[1] = 0x00;
+ auc_i2c_write_buf[2] = 0x00;
+ auc_i2c_write_buf[3] = 0x00;
+ reg_val[0] = 0x00;
+ reg_val[1] = 0x00;
+ ft6x06_i2c_Read(client, auc_i2c_write_buf, 4, reg_val, 2);
+ if(0xb0 == (reg_val[0] & 0xf0) && (0x03 + (j % 0x0ffd)) == (((reg_val[0] & 0x0f) << 8) |reg_val[1]))
+ {
+ DBG("[FTS] write a block data finished \n");
+ break;
+ }
+ msleep(1);
+ }
+ //msleep(FTS_PACKET_LENGTH / 6 + 1);
+ //DBG("write bytes:0x%04x\n", (j+1) * FTS_PACKET_LENGTH);
+ //delay_qt_ms(FTS_PACKET_LENGTH / 6 + 1);
+ }
+
+ if ((dw_lenth) % FTS_PACKET_LENGTH > 0) {
+ temp = packet_number * FTS_PACKET_LENGTH;
+ packet_buf[2] = (u8) (temp >> 8);
+ packet_buf[3] = (u8) temp;
+ temp = (dw_lenth) % FTS_PACKET_LENGTH;
+ packet_buf[4] = (u8) (temp >> 8);
+ packet_buf[5] = (u8) temp;
+
+ for (i = 0; i < temp; i++) {
+ packet_buf[6 + i] = pbt_buf[packet_number * FTS_PACKET_LENGTH + i];
+ bt_ecc ^= packet_buf[6 + i];
+ }
+
+ ft6x06_i2c_Write(client, packet_buf, temp + 6);
+
+ for(i = 0;i < 30;i++)
+ {
+ auc_i2c_write_buf[0] = 0x6a;
+ auc_i2c_write_buf[1] = 0x00;
+ auc_i2c_write_buf[2] = 0x00;
+ auc_i2c_write_buf[3] = 0x00;
+ reg_val[0] = 0x00;
+ reg_val[1] = 0x00;
+ ft6x06_i2c_Read(client, auc_i2c_write_buf, 4, reg_val, 2);
+ if(0xb0 == (reg_val[0] & 0xf0) && (0x03 + (j % 0x0ffd)) == (((reg_val[0] & 0x0f) << 8) |reg_val[1]))
+ {
+ DBG("[FTS] write a block data finished \n");
+ break;
+ }
+ msleep(1);
+ }
+ //msleep(20);
+ }
+
+
+ /*********Step 6: read out checksum***********************/
+ /*send the opration head */
+ DBG("Step 6: read out checksum\n");
+ auc_i2c_write_buf[0] = 0xcc;
+ ft6x06_i2c_Read(client, auc_i2c_write_buf, 1, reg_val, 1);
+ if (reg_val[0] != bt_ecc) {
+ dev_err(&client->dev, "[FTS]--ecc error! FW=%02x bt_ecc=%02x\n",
+ reg_val[0],
+ bt_ecc);
+ return -EIO;
+ }
+
+ /*********Step 7: reset the new FW***********************/
+ DBG("Step 7: reset the new FW\n");
+ auc_i2c_write_buf[0] = 0x07;
+ ft6x06_i2c_Write(client, auc_i2c_write_buf, 1);
+ msleep(300); /*make sure CTP startup normally */
+
+ return 0;
+}
+
+/*sysfs debug*/
+
+/*
+*get firmware size
+
+@firmware_name:firmware name
+*note:the firmware default path is sdcard.
+ if you want to change the dir, please modify by yourself.
+*/
+static int ft6x06_GetFirmwareSize(char *firmware_name)
+{
+ struct file *pfile = NULL;
+ struct inode *inode;
+ unsigned long magic;
+ off_t fsize = 0;
+ char filepath[128];
+ memset(filepath, 0, sizeof(filepath));
+
+ sprintf(filepath, "/sdcard/%s", firmware_name);
+
+ if (NULL == pfile)
+ pfile = filp_open(filepath, O_RDONLY, 0);
+
+ if (IS_ERR(pfile)) {
+ pr_err("error occured while opening file %s.\n", filepath);
+ return -EIO;
+ }
+
+ inode = pfile->f_dentry->d_inode;
+ magic = inode->i_sb->s_magic;
+ fsize = inode->i_size;
+ filp_close(pfile, NULL);
+ return fsize;
+}
+
+
+
+/*
+*read firmware buf for .bin file.
+
+@firmware_name: fireware name
+@firmware_buf: data buf of fireware
+
+note:the firmware default path is sdcard.
+ if you want to change the dir, please modify by yourself.
+*/
+static int ft6x06_ReadFirmware(char *firmware_name,
+ unsigned char *firmware_buf)
+{
+ struct file *pfile = NULL;
+ struct inode *inode;
+ unsigned long magic;
+ off_t fsize;
+ char filepath[128];
+ loff_t pos;
+ mm_segment_t old_fs;
+
+ memset(filepath, 0, sizeof(filepath));
+ sprintf(filepath, "/sdcard/%s", firmware_name);
+ if (NULL == pfile)
+ pfile = filp_open(filepath, O_RDONLY, 0);
+ if (IS_ERR(pfile)) {
+ pr_err("error occured while opening file %s.\n", filepath);
+ return -EIO;
+ }
+
+ inode = pfile->f_dentry->d_inode;
+ magic = inode->i_sb->s_magic;
+ fsize = inode->i_size;
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ pos = 0;
+ vfs_read(pfile, firmware_buf, fsize, &pos);
+ filp_close(pfile, NULL);
+ set_fs(old_fs);
+
+ return 0;
+}
+
+
+
+/*
+upgrade with *.bin file
+*/
+
+int fts_ctpm_fw_upgrade_with_app_file(struct i2c_client *client,
+ char *firmware_name)
+{
+ u8 *pbt_buf = NULL;
+ int i_ret;
+ int fwsize = ft6x06_GetFirmwareSize(firmware_name);
+
+ if (fwsize <= 0) {
+ dev_err(&client->dev, "%s ERROR:Get firmware size failed\n",
+ __func__);
+ return -EIO;
+ }
+
+ if (fwsize < 8 || fwsize > 32 * 1024) {
+ dev_dbg(&client->dev, "%s:FW length error\n", __func__);
+ return -EIO;
+ }
+
+ /*=========FW upgrade========================*/
+ pbt_buf = kmalloc(fwsize + 1, GFP_ATOMIC);
+
+ if (ft6x06_ReadFirmware(firmware_name, pbt_buf)) {
+ dev_err(&client->dev, "%s() - ERROR: request_firmware failed\n",
+ __func__);
+ kfree(pbt_buf);
+ return -EIO;
+ }
+
+ /*call the upgrade function */
+ i_ret = fts_ctpm_fw_upgrade(client, pbt_buf, fwsize);
+ if (i_ret != 0)
+ dev_err(&client->dev, "%s() - ERROR:[FTS] upgrade failed..\n",
+ __func__);
+ //else
+ //fts_ctpm_auto_clb(client);
+ kfree(pbt_buf);
+
+ return i_ret;
+}
+
+static ssize_t ft6x06_tpfwver_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ ssize_t num_read_chars = 0;
+ u8 fwver = 0;
+ struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+
+ mutex_lock(&g_device_mutex);
+
+ if (ft6x06_read_reg(client, FT6x06_REG_FW_VER, &fwver) < 0)
+ num_read_chars = snprintf(buf, PAGE_SIZE,
+ "get tp fw version fail!\n");
+ else
+ num_read_chars = snprintf(buf, PAGE_SIZE, "%02X\n", fwver);
+
+ mutex_unlock(&g_device_mutex);
+
+ return num_read_chars;
+}
+
+static ssize_t ft6x06_tpfwver_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ /*place holder for future use*/
+ return -EPERM;
+}
+
+
+
+static ssize_t ft6x06_tprwreg_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ /*place holder for future use*/
+ return -EPERM;
+}
+
+static ssize_t ft6x06_tprwreg_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+ ssize_t num_read_chars = 0;
+ int retval;
+ long unsigned int wmreg = 0;
+ u8 regaddr = 0xff, regvalue = 0xff;
+ u8 valbuf[5] = {0};
+
+ memset(valbuf, 0, sizeof(valbuf));
+ mutex_lock(&g_device_mutex);
+ num_read_chars = count - 1;
+
+ if (num_read_chars != 2) {
+ if (num_read_chars != 4) {
+ pr_info("please input 2 or 4 character\n");
+ goto error_return;
+ }
+ }
+
+ memcpy(valbuf, buf, num_read_chars);
+ retval = strict_strtoul(valbuf, 16, &wmreg);
+
+ if (0 != retval) {
+ dev_err(&client->dev, "%s() - ERROR: Could not convert the "\
+ "given input to a number." \
+ "The given input was: \"%s\"\n",
+ __func__, buf);
+ goto error_return;
+ }
+
+ if (2 == num_read_chars) {
+ /*read register*/
+ regaddr = wmreg;
+ if (ft6x06_read_reg(client, regaddr, &regvalue) < 0)
+ dev_err(&client->dev, "Could not read the register(0x%02x)\n",
+ regaddr);
+ else
+ pr_info("the register(0x%02x) is 0x%02x\n",
+ regaddr, regvalue);
+ } else {
+ regaddr = wmreg >> 8;
+ regvalue = wmreg;
+ if (ft6x06_write_reg(client, regaddr, regvalue) < 0)
+ dev_err(&client->dev, "Could not write the register(0x%02x)\n",
+ regaddr);
+ else
+ dev_err(&client->dev, "Write 0x%02x into register(0x%02x) successful\n",
+ regvalue, regaddr);
+ }
+
+error_return:
+ mutex_unlock(&g_device_mutex);
+
+ return count;
+}
+
+static ssize_t ft6x06_fwupdate_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ /* place holder for future use */
+ return -EPERM;
+}
+
+/*upgrade from *.i*/
+static ssize_t ft6x06_fwupdate_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct ft6x06_ts_data *data = NULL;
+ u8 uc_host_fm_ver;
+ int i_ret;
+ struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+
+ data = (struct ft6x06_ts_data *)i2c_get_clientdata(client);
+
+ mutex_lock(&g_device_mutex);
+
+ disable_irq(client->irq);
+ i_ret = fts_ctpm_fw_upgrade_with_i_file(client);
+ if (i_ret == 0) {
+ msleep(300);
+ uc_host_fm_ver = fts_ctpm_get_i_file_ver();
+ pr_info("%s [FTS] upgrade to new version 0x%x\n", __func__,
+ uc_host_fm_ver);
+ } else
+ dev_err(&client->dev, "%s ERROR:[FTS] upgrade failed.\n",
+ __func__);
+
+ enable_irq(client->irq);
+ mutex_unlock(&g_device_mutex);
+
+ return count;
+}
+
+static ssize_t ft6x06_fwupgradeapp_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ /*place holder for future use*/
+ return -EPERM;
+}
+
+
+/*upgrade from app.bin*/
+static ssize_t ft6x06_fwupgradeapp_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ char fwname[128];
+ struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+
+ memset(fwname, 0, sizeof(fwname));
+ sprintf(fwname, "%s", buf);
+ fwname[count - 1] = '\0';
+
+ mutex_lock(&g_device_mutex);
+ disable_irq(client->irq);
+
+ fts_ctpm_fw_upgrade_with_app_file(client, fwname);
+
+ enable_irq(client->irq);
+ mutex_unlock(&g_device_mutex);
+
+ return count;
+}
+
+
+/*sysfs */
+/*get the fw version
+*example:cat ftstpfwver
+*/
+static DEVICE_ATTR(ftstpfwver, S_IRUGO | S_IWUSR, ft6x06_tpfwver_show,
+ ft6x06_tpfwver_store);
+
+/*upgrade from *.i
+*example: echo 1 > ftsfwupdate
+*/
+static DEVICE_ATTR(ftsfwupdate, S_IRUGO | S_IWUSR, ft6x06_fwupdate_show,
+ ft6x06_fwupdate_store);
+
+/*read and write register
+*read example: echo 88 > ftstprwreg ---read register 0x88
+*write example:echo 8807 > ftstprwreg ---write 0x07 into register 0x88
+*
+*note:the number of input must be 2 or 4.if it not enough,please fill in the 0.
+*/
+static DEVICE_ATTR(ftstprwreg, S_IRUGO | S_IWUSR, ft6x06_tprwreg_show,
+ ft6x06_tprwreg_store);
+
+
+/*upgrade from app.bin
+*example:echo "*_app.bin" > ftsfwupgradeapp
+*/
+static DEVICE_ATTR(ftsfwupgradeapp, S_IRUGO | S_IWUSR, ft6x06_fwupgradeapp_show,
+ ft6x06_fwupgradeapp_store);
+
+
+/*add your attr in here*/
+static struct attribute *ft6x06_attributes[] = {
+ &dev_attr_ftstpfwver.attr,
+ &dev_attr_ftsfwupdate.attr,
+ &dev_attr_ftstprwreg.attr,
+ &dev_attr_ftsfwupgradeapp.attr,
+ NULL
+};
+
+static struct attribute_group ft6x06_attribute_group = {
+ .attrs = ft6x06_attributes
+};
+
+/*create sysfs for debug*/
+int ft6x06_create_sysfs(struct i2c_client *client)
+{
+ int err;
+ err = sysfs_create_group(&client->dev.kobj, &ft6x06_attribute_group);
+ if (0 != err) {
+ dev_err(&client->dev,
+ "%s() - ERROR: sysfs_create_group() failed.\n",
+ __func__);
+ sysfs_remove_group(&client->dev.kobj, &ft6x06_attribute_group);
+ return -EIO;
+ } else {
+ mutex_init(&g_device_mutex);
+ pr_info("ft6x06:%s() - sysfs_create_group() succeeded.\n",
+ __func__);
+ }
+ return err;
+}
+
+void ft6x06_release_sysfs(struct i2c_client *client)
+{
+ sysfs_remove_group(&client->dev.kobj, &ft6x06_attribute_group);
+ mutex_destroy(&g_device_mutex);
+}
+
+/*create apk debug channel*/
+#define PROC_UPGRADE 0
+#define PROC_READ_REGISTER 1
+#define PROC_WRITE_REGISTER 2
+#define PROC_AUTOCLB 4
+#define PROC_UPGRADE_INFO 5
+#define PROC_WRITE_DATA 6
+#define PROC_READ_DATA 7
+
+
+#define PROC_NAME "ft5x0x-debug"
+static unsigned char proc_operate_mode = PROC_UPGRADE;
+static struct proc_dir_entry *ft6x06_proc_entry;
+/*interface of write proc*/
+static int ft6x06_debug_write(struct file *filp,
+ const char __user *buff, unsigned long len, void *data)
+{
+ struct i2c_client *client = (struct i2c_client *)ft6x06_proc_entry->data;
+ unsigned char writebuf[FTS_PACKET_LENGTH];
+ int buflen = len;
+ int writelen = 0;
+ int ret = 0;
+
+ if (copy_from_user(&writebuf, buff, buflen)) {
+ dev_err(&client->dev, "%s:copy from user error\n", __func__);
+ return -EFAULT;
+ }
+ proc_operate_mode = writebuf[0];
+
+ switch (proc_operate_mode) {
+ case PROC_UPGRADE:
+ {
+ char upgrade_file_path[128];
+ memset(upgrade_file_path, 0, sizeof(upgrade_file_path));
+ sprintf(upgrade_file_path, "%s", writebuf + 1);
+ upgrade_file_path[buflen-1] = '\0';
+ DBG("%s\n", upgrade_file_path);
+ disable_irq(client->irq);
+
+ ret = fts_ctpm_fw_upgrade_with_app_file(client, upgrade_file_path);
+
+ enable_irq(client->irq);
+ if (ret < 0) {
+ dev_err(&client->dev, "%s:upgrade failed.\n", __func__);
+ return ret;
+ }
+ }
+ break;
+ case PROC_READ_REGISTER:
+ writelen = 1;
+ ret = ft6x06_i2c_Write(client, writebuf + 1, writelen);
+ if (ret < 0) {
+ dev_err(&client->dev, "%s:write iic error\n", __func__);
+ return ret;
+ }
+ break;
+ case PROC_WRITE_REGISTER:
+ writelen = 2;
+ ret = ft6x06_i2c_Write(client, writebuf + 1, writelen);
+ if (ret < 0) {
+ dev_err(&client->dev, "%s:write iic error\n", __func__);
+ return ret;
+ }
+ break;
+ case PROC_AUTOCLB:
+ DBG("%s: autoclb\n", __func__);
+ fts_ctpm_auto_clb(client);
+ break;
+ case PROC_READ_DATA:
+ case PROC_WRITE_DATA:
+ writelen = len - 1;
+ ret = ft6x06_i2c_Write(client, writebuf + 1, writelen);
+ if (ret < 0) {
+ dev_err(&client->dev, "%s:write iic error\n", __func__);
+ return ret;
+ }
+ break;
+ default:
+ break;
+ }
+
+
+ return len;
+}
+
+/*interface of read proc*/
+static int ft6x06_debug_read( char *page, char **start,
+ off_t off, int count, int *eof, void *data )
+{
+ struct i2c_client *client = (struct i2c_client *)ft6x06_proc_entry->data;
+ int ret = 0;
+ unsigned char buf[PAGE_SIZE];
+ int num_read_chars = 0;
+ int readlen = 0;
+ u8 regvalue = 0x00, regaddr = 0x00;
+
+ switch (proc_operate_mode) {
+ case PROC_UPGRADE:
+ /*after calling ft5x0x_debug_write to upgrade*/
+ regaddr = 0xA6;
+ ret = ft6x06_read_reg(client, regaddr, &regvalue);
+ if (ret < 0)
+ num_read_chars = sprintf(buf, "%s", "get fw version failed.\n");
+ else
+ num_read_chars = sprintf(buf, "current fw version:0x%02x\n", regvalue);
+ break;
+ case PROC_READ_REGISTER:
+ readlen = 1;
+ ret = ft6x06_i2c_Read(client, NULL, 0, buf, readlen);
+ if (ret < 0) {
+ dev_err(&client->dev, "%s:read iic error\n", __func__);
+ return ret;
+ }
+ num_read_chars = 1;
+ break;
+ case PROC_READ_DATA:
+ readlen = count;
+ ret = ft6x06_i2c_Read(client, NULL, 0, buf, readlen);
+ if (ret < 0) {
+ dev_err(&client->dev, "%s:read iic error\n", __func__);
+ return ret;
+ }
+
+ num_read_chars = readlen;
+ break;
+ case PROC_WRITE_DATA:
+ break;
+ default:
+ break;
+ }
+
+ memcpy(page, buf, num_read_chars);
+ return num_read_chars;
+}
+int ft6x06_create_apk_debug_channel(struct i2c_client * client)
+{
+ ft6x06_proc_entry = create_proc_entry(PROC_NAME, 0777, NULL);
+ if (NULL == ft6x06_proc_entry) {
+ dev_err(&client->dev, "Couldn't create proc entry!\n");
+ return -ENOMEM;
+ } else {
+ dev_info(&client->dev, "Create proc entry success!\n");
+ ft6x06_proc_entry->data = client;
+ ft6x06_proc_entry->write_proc = ft6x06_debug_write;
+ ft6x06_proc_entry->read_proc = ft6x06_debug_read;
+ }
+ return 0;
+}
+
+void ft6x06_release_apk_debug_channel(void)
+{
+ if (ft6x06_proc_entry)
+ remove_proc_entry(PROC_NAME, NULL);
+}
+
diff --git a/drivers/input/touchscreen/ft6x0x/ft6x06_ex_fun.h b/drivers/input/touchscreen/ft6x0x/ft6x06_ex_fun.h
new file mode 100755
index 00000000..e25675c0
--- /dev/null
+++ b/drivers/input/touchscreen/ft6x0x/ft6x06_ex_fun.h
@@ -0,0 +1,79 @@
+#ifndef __LINUX_FT6X06_EX_FUN_H__
+#define __LINUX_FT6X06_EX_FUN_H__
+
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/semaphore.h>
+#include <linux/mutex.h>
+#include <linux/interrupt.h>
+#include <mach/irqs.h>
+
+#include <linux/syscalls.h>
+#include <asm/unistd.h>
+#include <asm/uaccess.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+
+
+
+#define FT_UPGRADE_AA 0xAA
+#define FT_UPGRADE_55 0x55
+
+
+//upgrade config of FT6X06
+/*
+#define FT6X06_UPGRADE_AA_DELAY 100
+#define FT6X06_UPGRADE_55_DELAY 10
+#define FT6X06_UPGRADE_ID_1 0x79
+#define FT6X06_UPGRADE_ID_2 0x08
+#define FT6X06_UPGRADE_READID_DELAY 10
+#define FT6X06_UPGRADE_EARSE_DELAY 2000
+*/
+
+/*upgrade config of FT6X36*/
+#define FT6X06_UPGRADE_AA_DELAY 10
+#define FT6X06_UPGRADE_55_DELAY 10
+#define FT6X06_UPGRADE_ID_1 0x79
+#define FT6X06_UPGRADE_ID_2 0x18
+#define FT6X06_UPGRADE_READID_DELAY 10
+#define FT6X06_UPGRADE_EARSE_DELAY 2000
+
+#define FTS_PACKET_LENGTH 128
+#define FTS_SETTING_BUF_LEN 128
+
+#define FTS_UPGRADE_LOOP 20
+
+#define FTS_FACTORYMODE_VALUE 0x40
+#define FTS_WORKMODE_VALUE 0x00
+
+//#define AUTO_CLB
+#define FTS_DBG
+#ifdef FTS_DBG
+#define DBG(fmt, args...) printk("[FTS]" fmt, ## args)
+#else
+#define DBG(fmt, args...) do{}while(0)
+#endif
+
+/*create sysfs for debug*/
+int ft6x06_create_sysfs(struct i2c_client * client);
+
+void ft6x06_release_sysfs(struct i2c_client * client);
+
+int ft6x06_create_apk_debug_channel(struct i2c_client *client);
+
+void ft6x06_release_apk_debug_channel(void);
+
+/*
+*ft6x06_write_reg- write register
+*@client: handle of i2c
+*@regaddr: register address
+*@regvalue: register value
+*
+*/
+int ft6x06_write_reg(struct i2c_client * client,u8 regaddr, u8 regvalue);
+
+int ft6x06_read_reg(struct i2c_client * client,u8 regaddr, u8 *regvalue);
+
+#endif
diff --git a/drivers/input/touchscreen/ft6x0x/ft6x06_ts.c b/drivers/input/touchscreen/ft6x0x/ft6x06_ts.c
new file mode 100755
index 00000000..56148177
--- /dev/null
+++ b/drivers/input/touchscreen/ft6x0x/ft6x06_ts.c
@@ -0,0 +1,511 @@
+/* drivers/input/touchscreen/ft5x06_ts.c
+ *
+ * FocalTech ft6x06 TouchScreen driver.
+ *
+ * Copyright (c) 2010 Focal tech Ltd.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/input/mt.h>
+#include "ft6x06_ts.h"
+//#include <linux/earlysuspend.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <mach/irqs.h>
+#include <linux/kernel.h>
+#include <linux/semaphore.h>
+#include <linux/mutex.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/syscalls.h>
+#include <linux/unistd.h>
+#include <linux/uaccess.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+
+//#define FTS_CTL_FACE_DETECT
+#define FTS_CTL_IIC
+#define SYSFS_DEBUG
+#define FTS_APK_DEBUG
+//#define FT6X06_DOWNLOAD
+
+#ifdef FTS_CTL_IIC
+#include "focaltech_ctl.h"
+#endif
+#ifdef FTS_CTL_FACE_DETECT
+#include "ft_psensor_drv.h"
+#endif
+#ifdef SYSFS_DEBUG
+#include "ft6x06_ex_fun.h"
+#endif
+
+#if 0
+struct ts_event {
+ u16 au16_x[CFG_MAX_TOUCH_POINTS]; /*x coordinate */
+ u16 au16_y[CFG_MAX_TOUCH_POINTS]; /*y coordinate */
+ u8 au8_touch_event[CFG_MAX_TOUCH_POINTS]; /*touch event:
+ 0 -- down; 1-- up; 2 -- contact */
+ u8 au8_finger_id[CFG_MAX_TOUCH_POINTS]; /*touch ID */
+ u16 pressure;
+ u8 touch_point;
+};
+
+struct ft6x06_ts_data {
+ unsigned int irq;
+ unsigned int x_max;
+ unsigned int y_max;
+ struct i2c_client *client;
+ struct input_dev *input_dev;
+ struct ts_event event;
+ struct ft6x06_platform_data *pdata;
+#ifdef CONFIG_PM
+ struct early_suspend *early_suspend;
+#endif
+};
+
+#define FTS_POINT_UP 0x01
+#define FTS_POINT_DOWN 0x00
+#define FTS_POINT_CONTACT 0x02
+#endif
+
+/*
+*ft6x06_i2c_Read-read data and write data by i2c
+*@client: handle of i2c
+*@writebuf: Data that will be written to the slave
+*@writelen: How many bytes to write
+*@readbuf: Where to store data read from slave
+*@readlen: How many bytes to read
+*
+*Returns negative errno, else the number of messages executed
+*
+*
+*/
+int ft6x06_i2c_Read(struct i2c_client *client, char *writebuf,
+ int writelen, char *readbuf, int readlen)
+{
+ int ret;
+
+ if (writelen > 0) {
+ struct i2c_msg msgs[] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = writelen,
+ .buf = writebuf,
+ },
+ {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = readlen,
+ .buf = readbuf,
+ },
+ };
+ ret = i2c_transfer(client->adapter, msgs, 2);
+ if (ret < 0)
+ dev_err(&client->dev, "f%s: i2c read error.\n",
+ __func__);
+ } else {
+ struct i2c_msg msgs[] = {
+ {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = readlen,
+ .buf = readbuf,
+ },
+ };
+ ret = i2c_transfer(client->adapter, msgs, 1);
+ if (ret < 0)
+ dev_err(&client->dev, "%s:i2c read error.\n", __func__);
+ }
+ return ret;
+}
+/*write data by i2c*/
+int ft6x06_i2c_Write(struct i2c_client *client, char *writebuf, int writelen)
+{
+ int ret;
+
+ struct i2c_msg msg[] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = writelen,
+ .buf = writebuf,
+ },
+ };
+
+ ret = i2c_transfer(client->adapter, msg, 1);
+ if (ret < 0)
+ dev_err(&client->dev, "%s i2c write error.\n", __func__);
+
+ return ret;
+}
+
+#if 0
+/*Read touch point information when the interrupt is asserted.*/
+static int ft6x06_read_Touchdata(struct ft6x06_ts_data *data)
+{
+ struct ts_event *event = &data->event;
+ u8 buf[POINT_READ_BUF] = { 0 };
+ int ret = -1;
+ int i = 0;
+ u8 pointid = FT_MAX_ID;
+
+ ret = ft6x06_i2c_Read(data->client, buf, 1, buf, POINT_READ_BUF);
+ if (ret < 0) {
+ dev_err(&data->client->dev, "%s read touchdata failed.\n",
+ __func__);
+ return ret;
+ }
+ memset(event, 0, sizeof(struct ts_event));
+
+ //event->touch_point = buf[2] & 0x0F;
+
+ //event->touch_point = 0;
+
+ for (i = 0; i < CFG_MAX_TOUCH_POINTS; i++)
+ {
+ pointid = (buf[FT_TOUCH_ID_POS + FT_TOUCH_STEP * i]) >> 4;
+ if (pointid >= FT_MAX_ID)
+ break;
+ else
+ event->touch_point++;
+ event->au16_x[i] =
+ (s16) (buf[FT_TOUCH_X_H_POS + FT_TOUCH_STEP * i] & 0x0F) <<
+ 8 | (s16) buf[FT_TOUCH_X_L_POS + FT_TOUCH_STEP * i];
+ event->au16_y[i] =
+ (s16) (buf[FT_TOUCH_Y_H_POS + FT_TOUCH_STEP * i] & 0x0F) <<
+ 8 | (s16) buf[FT_TOUCH_Y_L_POS + FT_TOUCH_STEP * i];
+ event->au8_touch_event[i] =
+ buf[FT_TOUCH_EVENT_POS + FT_TOUCH_STEP * i] >> 6;
+ event->au8_finger_id[i] =
+ (buf[FT_TOUCH_ID_POS + FT_TOUCH_STEP * i]) >> 4;
+ }
+
+ //event->pressure = FT_PRESS;
+
+ return 0;
+}
+
+/*
+*report the point information
+*/
+static void ft6x06_report_value(struct ft6x06_ts_data *data)
+{
+ struct ts_event *event = &data->event;
+ int i = 0;
+ int up_point = 0;
+
+ for (i = 0; i < event->touch_point; i++)
+ {
+ input_mt_slot(data->input_dev, event->au8_finger_id[i]);
+
+ if (event->au8_touch_event[i]== 0 || event->au8_touch_event[i] == 2)
+ {
+ input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER,
+ true);
+ //input_report_abs(data->input_dev, ABS_MT_TRACKING_ID,
+ //event->au8_finger_id[i]);
+ input_report_abs(data->input_dev, ABS_MT_PRESSURE,
+ 0x3f);
+ input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR,
+ 0x05);
+ input_report_abs(data->input_dev, ABS_MT_POSITION_X,
+ event->au16_x[i]);
+ input_report_abs(data->input_dev, ABS_MT_POSITION_Y,
+ event->au16_y[i]);
+
+ }
+ else
+ {
+ up_point++;
+ input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER,
+ false);
+ }
+
+ }
+
+ if(event->touch_point == up_point)
+ input_report_key(data->input_dev, BTN_TOUCH, 0);
+ else
+ input_report_key(data->input_dev, BTN_TOUCH, 1);
+
+ input_sync(data->input_dev);
+
+}
+
+/*The ft6x06 device will signal the host about TRIGGER_FALLING.
+*Processed when the interrupt is asserted.
+*/
+static irqreturn_t ft6x06_ts_interrupt(int irq, void *dev_id)
+{
+ struct ft6x06_ts_data *ft6x06_ts = dev_id;
+ int ret = 0;
+ disable_irq_nosync(ft6x06_ts->irq);
+
+ ret = ft6x06_read_Touchdata(ft6x06_ts);
+ if (ret == 0)
+ ft6x06_report_value(ft6x06_ts);
+
+ enable_irq(ft6x06_ts->irq);
+
+ //printk(KERN_WARNING "interrupt \n");
+
+ return IRQ_HANDLED;
+}
+
+static int ft6x06_ts_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct ft6x06_platform_data *pdata =
+ (struct ft6x06_platform_data *)client->dev.platform_data;
+ struct ft6x06_ts_data *ft6x06_ts;
+ struct input_dev *input_dev;
+ int err = 0;
+ unsigned char uc_reg_value;
+ unsigned char uc_reg_addr;
+
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ err = -ENODEV;
+ goto exit_check_functionality_failed;
+ }
+
+ ft6x06_ts = kzalloc(sizeof(struct ft6x06_ts_data), GFP_KERNEL);
+
+ if (!ft6x06_ts) {
+ err = -ENOMEM;
+ goto exit_alloc_data_failed;
+ }
+
+ i2c_set_clientdata(client, ft6x06_ts);
+ ft6x06_ts->irq = client->irq;
+ ft6x06_ts->client = client;
+ ft6x06_ts->pdata = pdata;
+ ft6x06_ts->x_max = pdata->x_max - 1;
+ ft6x06_ts->y_max = pdata->y_max - 1;
+ ft6x06_ts->pdata->irq = ft6x06_ts->irq;
+ client->irq = ft6x06_ts->irq;
+ pr_info("irq = %d\n", client->irq);
+
+#ifdef CONFIG_PM
+ #if 0
+ err = gpio_request(pdata->reset, "ft6x06 reset");
+ if (err < 0) {
+ dev_err(&client->dev, "%s:failed to set gpio reset.\n",
+ __func__);
+ goto exit_request_reset;
+ }
+ #endif
+#endif
+
+ err = request_threaded_irq(client->irq, NULL, ft6x06_ts_interrupt,
+ IRQF_TRIGGER_FALLING, client->dev.driver->name,
+ ft6x06_ts);
+
+ if (err < 0) {
+ dev_err(&client->dev, "ft6x06_probe: request irq failed\n");
+ goto exit_irq_request_failed;
+ }
+ disable_irq(client->irq);
+
+ input_dev = input_allocate_device();
+ if (!input_dev) {
+ err = -ENOMEM;
+ dev_err(&client->dev, "failed to allocate input device\n");
+ goto exit_input_dev_alloc_failed;
+ }
+
+ ft6x06_ts->input_dev = input_dev;
+
+ __set_bit(EV_ABS, input_dev->evbit);
+ __set_bit(EV_KEY, input_dev->evbit);
+ __set_bit(BTN_TOUCH, input_dev->keybit);
+ __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+
+ input_mt_init_slots(input_dev, MT_MAX_TOUCH_POINTS);
+ input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
+ 0, PRESS_MAX, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_POSITION_X,
+ 0, ft6x06_ts->x_max, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
+ 0, ft6x06_ts->y_max, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_PRESSURE,
+ 0, PRESS_MAX, 0, 0);
+
+ input_dev->name = FT6X06_NAME;
+ err = input_register_device(input_dev);
+ if (err) {
+ dev_err(&client->dev,
+ "ft6x06_ts_probe: failed to register input device: %s\n",
+ dev_name(&client->dev));
+ goto exit_input_register_device_failed;
+ }
+ /*make sure CTP already finish startup process */
+ msleep(150);
+
+ /*get some register information */
+ uc_reg_addr = FT6x06_REG_FW_VER;
+ ft6x06_i2c_Read(client, &uc_reg_addr, 1, &uc_reg_value, 1);
+ dev_dbg(&client->dev, "[FTS] Firmware version = 0x%x\n", uc_reg_value);
+
+ uc_reg_addr = FT6x06_REG_POINT_RATE;
+ ft6x06_i2c_Read(client, &uc_reg_addr, 1, &uc_reg_value, 1);
+ dev_dbg(&client->dev, "[FTS] report rate is %dHz.\n",
+ uc_reg_value * 10);
+
+ uc_reg_addr = FT6x06_REG_THGROUP;
+ ft6x06_i2c_Read(client, &uc_reg_addr, 1, &uc_reg_value, 1);
+ dev_dbg(&client->dev, "[FTS] touch threshold is %d.\n",
+ uc_reg_value * 4);
+
+#ifdef SYSFS_DEBUG
+ ft6x06_create_sysfs(client);
+#endif
+
+#ifdef FTS_CTL_IIC
+ if (ft_rw_iic_drv_init(client) < 0)
+ dev_err(&client->dev, "%s:[FTS] create fts control iic driver failed\n",
+ __func__);
+#endif
+
+#ifdef FTS_APK_DEBUG
+ ft6x06_create_apk_debug_channel(client);
+#endif
+
+#ifdef FTS_CTL_FACE_DETECT
+ if (ft_psensor_drv_init(client) < 0)
+ dev_err(&client->dev, "%s:[FTS] create fts control psensor driver failed\n",
+ __func__);
+#endif
+
+ enable_irq(client->irq);
+ return 0;
+
+exit_input_register_device_failed:
+ input_free_device(input_dev);
+
+exit_input_dev_alloc_failed:
+ free_irq(client->irq, ft6x06_ts);
+#ifdef CONFIG_PM
+exit_request_reset:
+ gpio_free(ft6x06_ts->pdata->reset);
+#endif
+
+exit_irq_request_failed:
+ i2c_set_clientdata(client, NULL);
+ kfree(ft6x06_ts);
+
+exit_alloc_data_failed:
+exit_check_functionality_failed:
+ return err;
+}
+
+#ifdef CONFIG_PM
+static void ft6x06_ts_suspend(struct early_suspend *handler)
+{
+ struct ft6x06_ts_data *ts = container_of(handler, struct ft6x06_ts_data,
+ early_suspend);
+
+ dev_dbg(&ts->client->dev, "[FTS]ft6x06 suspend\n");
+ disable_irq(ts->pdata->irq);
+}
+
+static void ft6x06_ts_resume(struct early_suspend *handler)
+{
+ struct ft6x06_ts_data *ts = container_of(handler, struct ft6x06_ts_data,
+ early_suspend);
+
+ dev_dbg(&ts->client->dev, "[FTS]ft6x06 resume.\n");
+ gpio_set_value(ts->pdata->reset, 0);
+ msleep(20);
+ gpio_set_value(ts->pdata->reset, 1);
+ enable_irq(ts->pdata->irq);
+}
+#else
+#define ft6x06_ts_suspend NULL
+#define ft6x06_ts_resume NULL
+#endif
+
+static int __devexit ft6x06_ts_remove(struct i2c_client *client)
+{
+ struct ft6x06_ts_data *ft6x06_ts;
+ ft6x06_ts = i2c_get_clientdata(client);
+ input_unregister_device(ft6x06_ts->input_dev);
+ #ifdef CONFIG_PM
+ gpio_free(ft6x06_ts->pdata->reset);
+ #endif
+
+ #ifdef SYSFS_DEBUG
+ ft6x06_release_sysfs(client);
+ #endif
+ #ifdef FTS_CTL_IIC
+ ft_rw_iic_drv_exit();
+ #endif
+ #ifdef FTS_CTL_FACE_DETECT
+ ft_psensor_drv_exit();
+ #endif
+ free_irq(client->irq, ft6x06_ts);
+ kfree(ft6x06_ts);
+ i2c_set_clientdata(client, NULL);
+ return 0;
+}
+
+static const struct i2c_device_id ft6x06_ts_id[] = {
+ {FT6X06_NAME, 0},
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, ft6x06_ts_id);
+
+static struct i2c_driver ft6x06_ts_driver = {
+ .probe = ft6x06_ts_probe,
+ .remove = __devexit_p(ft6x06_ts_remove),
+ .id_table = ft6x06_ts_id,
+ .suspend = ft6x06_ts_suspend,
+ .resume = ft6x06_ts_resume,
+ .driver = {
+ .name = FT6X06_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init ft6x06_ts_init(void)
+{
+ int ret;
+ ret = i2c_add_driver(&ft6x06_ts_driver);
+ if (ret) {
+ printk(KERN_WARNING "Adding ft6x06 driver failed "
+ "(errno = %d)\n", ret);
+ } else {
+ pr_info("Successfully added driver %s\n",
+ ft6x06_ts_driver.driver.name);
+ }
+ return ret;
+}
+
+static void __exit ft6x06_ts_exit(void)
+{
+ i2c_del_driver(&ft6x06_ts_driver);
+}
+
+module_init(ft6x06_ts_init);
+module_exit(ft6x06_ts_exit);
+
+MODULE_AUTHOR("<luowj>");
+MODULE_DESCRIPTION("FocalTech ft6x06 TouchScreen driver");
+MODULE_LICENSE("GPL");
+
+#endif
diff --git a/drivers/input/touchscreen/ft6x0x/ft6x06_ts.h b/drivers/input/touchscreen/ft6x0x/ft6x06_ts.h
new file mode 100755
index 00000000..83859c05
--- /dev/null
+++ b/drivers/input/touchscreen/ft6x0x/ft6x06_ts.h
@@ -0,0 +1,52 @@
+#ifndef __LINUX_FT6X06_TS_H__
+#define __LINUX_FT6X06_TS_H__
+
+/* -- dirver configure -- */
+#define CFG_MAX_TOUCH_POINTS 2
+#define MT_MAX_TOUCH_POINTS 9
+
+#define PRESS_MAX 0xFF
+#define FT_PRESS 0x7F
+
+#define Proximity_Max 32
+
+#define FT_FACE_DETECT_ON 0xc0
+#define FT_FACE_DETECT_OFF 0xe0
+
+#define FT_FACE_DETECT_ENABLE 1
+#define FT_FACE_DETECT_DISABLE 0
+#define FT_FACE_DETECT_REG 0xB0
+
+#define FT6X06_NAME "ft6x06_ts"
+
+#define FT_MAX_ID 0x0F
+#define FT_TOUCH_STEP 6
+#define FT_FACE_DETECT_POS 1
+#define FT_TOUCH_X_H_POS 3
+#define FT_TOUCH_X_L_POS 4
+#define FT_TOUCH_Y_H_POS 5
+#define FT_TOUCH_Y_L_POS 6
+#define FT_TOUCH_EVENT_POS 3
+#define FT_TOUCH_ID_POS 5
+
+#define POINT_READ_BUF (3 + FT_TOUCH_STEP * CFG_MAX_TOUCH_POINTS)
+
+/*register address*/
+#define FT6x06_REG_FW_VER 0xA6
+#define FT6x06_REG_POINT_RATE 0x88
+#define FT6x06_REG_THGROUP 0x80
+
+int ft6x06_i2c_Read(struct i2c_client *client, char *writebuf, int writelen,
+ char *readbuf, int readlen);
+int ft6x06_i2c_Write(struct i2c_client *client, char *writebuf, int writelen);
+
+/* The platform data for the Focaltech ft6x06 touchscreen driver */
+struct ft6x06_platform_data {
+ unsigned int x_max;
+ unsigned int y_max;
+ unsigned long irqflags;
+ unsigned int irq;
+ unsigned int reset;
+};
+
+#endif
diff --git a/drivers/input/touchscreen/ft6x0x/ini.c b/drivers/input/touchscreen/ft6x0x/ini.c
new file mode 100755
index 00000000..a4f8dc38
--- /dev/null
+++ b/drivers/input/touchscreen/ft6x0x/ini.c
@@ -0,0 +1,406 @@
+#include <linux/string.h>
+#include <asm/unistd.h>
+#include <linux/slab.h>
+
+#include "ini.h"
+
+
+char CFG_SSL = '['; /* 项标志符Section Symbol --可根据特殊需要进行定义更改,如 { }等*/
+char CFG_SSR = ']'; /* 项标志符Section Symbol --可根据特殊需要进行定义更改,如 { }等*/
+char CFG_NIS = ':'; /* name 与 index 之间的分隔符 */
+char CFG_NTS = '#'; /* 注释符*/
+
+static char * ini_str_trim_r(char * buf);
+static char * ini_str_trim_l(char * buf);
+static int ini_file_get_line(char *filedata, char *buffer, int maxlen);
+static int ini_split_key_value(char *buf, char **key, char **val);
+static long atol(char *nptr);
+
+
+/*************************************************************
+Function: 获得key的值
+Input: char * filedata 文件;char * section 项值;char * key 键值
+Output: char * value key的值
+Return: 0 SUCCESS
+ -1 未找到section
+ -2 未找到key
+ -10 文件打开失败
+ -12 读取文件失败
+ -14 文件格式错误
+ -22 超出缓冲区大小
+Note:
+*************************************************************/
+int ini_get_key(char *filedata, char * section, char * key, char * value)
+{
+ //char buf1[MAX_CFG_BUF + 1], buf2[MAX_CFG_BUF + 1];
+ char *buf1, *buf2;
+ char *key_ptr, *val_ptr;
+ int n, ret;
+ int dataoff = 0;
+
+ *value='\0';
+
+ buf1 = kzalloc(MAX_CFG_BUF + 1, GFP_KERNEL);
+ if(!buf1){
+ printk("buf1: mem alloc failed.\n");
+ return -ENOMEM;
+ }
+ buf2 = kzalloc(MAX_CFG_BUF + 1, GFP_KERNEL);
+ if(!buf2){
+ printk("buf2: mem alloc failed.\n");
+ kfree(buf1);
+ return -ENOMEM;
+ }
+
+ while(1) { /* 搜找项section */
+ ret = CFG_ERR_READ_FILE;
+ n = ini_file_get_line(filedata+dataoff, buf1, MAX_CFG_BUF);
+ dataoff += n;
+ if(n < -1)
+ goto r_cfg_end;
+ ret = CFG_SECTION_NOT_FOUND;
+ if(n < 0)
+ goto r_cfg_end; /* 文件尾,未发现 */
+
+ n = strlen(ini_str_trim_l(ini_str_trim_r(buf1)));
+ if(n == 0 || buf1[0] == CFG_NTS)
+ continue; /* 空行 或 注释行 */
+
+ ret = CFG_ERR_FILE_FORMAT;
+ if(n > 2 && ((buf1[0] == CFG_SSL && buf1[n-1] != CFG_SSR)))
+ goto r_cfg_end;
+ if(buf1[0] == CFG_SSL) {
+ buf1[n-1] = 0x00;
+ if(strcmp(buf1+1, section) == 0)
+ break; /* 找到项section */
+ }
+ }
+
+ while(1){ /* 搜找key */
+ ret = CFG_ERR_READ_FILE;
+ n = ini_file_get_line(filedata+dataoff, buf1, MAX_CFG_BUF);
+ dataoff += n;
+ if(n < -1)
+ goto r_cfg_end;
+ ret = CFG_KEY_NOT_FOUND;
+ if(n < 0)
+ goto r_cfg_end;/* 文件尾,未发现key */
+
+ n = strlen(ini_str_trim_l(ini_str_trim_r(buf1)));
+ if(n == 0 || buf1[0] == CFG_NTS)
+ continue; /* 空行 或 注释行 */
+ ret = CFG_KEY_NOT_FOUND;
+ if(buf1[0] == CFG_SSL)
+ goto r_cfg_end;
+ if(buf1[n-1] == '+') { /* 遇+号表示下一行继续 */
+ buf1[n-1] = 0x00;
+ while(1) {
+ ret = CFG_ERR_READ_FILE;
+ n = ini_file_get_line(filedata+dataoff, buf2, MAX_CFG_BUF);
+ dataoff += n;
+ if(n < -1)
+ goto r_cfg_end;
+ if(n < 0)
+ break;/* 文件结束 */
+
+ n = strlen(ini_str_trim_r(buf2));
+ ret = CFG_ERR_EXCEED_BUF_SIZE;
+ if(n > 0 && buf2[n-1] == '+'){/* 遇+号表示下一行继续 */
+ buf2[n-1] = 0x00;
+ if( (strlen(buf1) + strlen(buf2)) > MAX_CFG_BUF)
+ goto r_cfg_end;
+ strcat(buf1, buf2);
+ continue;
+ }
+ if(strlen(buf1) + strlen(buf2) > MAX_CFG_BUF)
+ goto r_cfg_end;
+ strcat(buf1, buf2);
+ break;
+ }
+ }
+ ret = CFG_ERR_FILE_FORMAT;
+ if(ini_split_key_value(buf1, &key_ptr, &val_ptr) != 1)
+ goto r_cfg_end;
+ ini_str_trim_l(ini_str_trim_r(key_ptr));
+ if(strcmp(key_ptr, key) != 0)
+ continue; /* 和key值不匹配 */
+ strcpy(value, val_ptr);
+ break;
+ }
+ ret = CFG_OK;
+r_cfg_end:
+ //if(fp != NULL) fclose(fp);
+ kfree(buf1);
+ kfree(buf2);
+ return ret;
+}
+/*************************************************************
+Function: 获得所有section
+Input: char *filename 文件,int max 最大可返回的section的个数
+Output: char *sections[] 存放section名字
+Return: 返回section个数。若出错,返回负数。
+ -10 文件打开出错
+ -12 文件读取错误
+ -14 文件格式错误
+Note:
+*************************************************************/
+int ini_get_sections(char *filedata, unsigned char * sections[], int max)
+{
+ //FILE *fp;
+ char buf1[MAX_CFG_BUF + 1];
+ int n, n_sections = 0, ret;
+ int dataoff = 0;
+
+// if((fp = fopen(filename, "rb")) == NULL)
+// return CFG_ERR_OPEN_FILE;
+
+ while(1) {/*搜找项section */
+ ret = CFG_ERR_READ_FILE;
+ n = ini_file_get_line(filedata+dataoff, buf1, MAX_CFG_BUF);
+ dataoff += n;
+ if(n < -1)
+ goto cfg_scts_end;
+ if(n < 0)
+ break;/* 文件尾 */
+ n = strlen(ini_str_trim_l(ini_str_trim_r(buf1)));
+ if(n == 0 || buf1[0] == CFG_NTS)
+ continue; /* 空行 或 注释行 */
+ ret = CFG_ERR_FILE_FORMAT;
+ if(n > 2 && ((buf1[0] == CFG_SSL && buf1[n-1] != CFG_SSR)))
+ goto cfg_scts_end;
+ if(buf1[0] == CFG_SSL) {
+ if (max!=0){
+ buf1[n-1] = 0x00;
+ strcpy((char *)sections[n_sections], buf1+1);
+ if (n_sections>=max)
+ break; /* 超过可返回最大个数 */
+ }
+ n_sections++;
+ }
+
+ }
+ ret = n_sections;
+cfg_scts_end:
+// if(fp != NULL)
+// fclose(fp);
+ return ret;
+}
+
+
+/*************************************************************
+Function: 去除字符串右边的空字符
+Input: char * buf 字符串指针
+Output:
+Return: 字符串指针
+Note:
+*************************************************************/
+static char * ini_str_trim_r(char * buf)
+{
+ int len,i;
+ char tmp[128];
+
+ memset(tmp, 0, sizeof(tmp));
+ len = strlen(buf);
+// tmp = (char *)malloc(len);
+
+ memset(tmp,0x00,len);
+ for(i = 0;i < len;i++) {
+ if (buf[i] !=' ')
+ break;
+ }
+ if (i < len) {
+ strncpy(tmp,(buf+i),(len-i));
+ }
+ strncpy(buf,tmp,len);
+// free(tmp);
+ return buf;
+}
+
+/*************************************************************
+Function: 去除字符串左边的空字符
+Input: char * buf 字符串指针
+Output:
+Return: 字符串指针
+Note:
+*************************************************************/
+static char * ini_str_trim_l(char * buf)
+{
+ int len,i;
+ char tmp[128];
+
+ memset(tmp, 0, sizeof(tmp));
+ len = strlen(buf);
+ //tmp = (char *)malloc(len);
+
+ memset(tmp,0x00,len);
+
+ for(i = 0;i < len;i++) {
+ if (buf[len-i-1] !=' ')
+ break;
+ }
+ if (i < len) {
+ strncpy(tmp,buf,len-i);
+ }
+ strncpy(buf,tmp,len);
+ //free(tmp);
+ return buf;
+}
+/*************************************************************
+Function: 从文件中读取一行
+Input: FILE *fp 文件句柄;int maxlen 缓冲区最大长度
+Output: char *buffer 一行字符串
+Return: >0 实际读的长度
+ -1 文件结束
+ -2 读文件出错
+Note:
+*************************************************************/
+static int ini_file_get_line(char *filedata, char *buffer, int maxlen)
+{
+ int i, j;
+ char ch1;
+
+ for(i=0, j=0; i<maxlen; j++) {
+ ch1 = filedata[j];
+ if(ch1 == '\n' || ch1 == 0x00)
+ break; /* 换行 */
+ if(ch1 == '\f' || ch1 == 0x1A) { /* '\f':换页符也算有效字符 */
+ buffer[i++] = ch1;
+ break;
+ }
+ if(ch1 != '\r') buffer[i++] = ch1; /* 忽略回车符 */
+ }
+ buffer[i] = '\0';
+ return i+2;
+}
+/*************************************************************
+Function: 分离key和value
+ key=val
+ jack = liaoyuewang
+ | | |
+ k1 k2 i
+Input: char *buf
+Output: char **key, char **val
+Return: 1 --- ok
+ 0 --- blank line
+ -1 --- no key, "= val"
+ -2 --- only key, no '='
+Note:
+*************************************************************/
+static int ini_split_key_value(char *buf, char **key, char **val)
+{
+ int i, k1, k2, n;
+
+ if((n = strlen((char *)buf)) < 1)
+ return 0;
+ for(i = 0; i < n; i++)
+ if(buf[i] != ' ' && buf[i] != '\t')
+ break;
+
+ if(i >= n)
+ return 0;
+
+ if(buf[i] == '=')
+ return -1;
+
+ k1 = i;
+ for(i++; i < n; i++)
+ if(buf[i] == '=')
+ break;
+
+ if(i >= n)
+ return -2;
+ k2 = i;
+
+ for(i++; i < n; i++)
+ if(buf[i] != ' ' && buf[i] != '\t')
+ break;
+
+ buf[k2] = '\0';
+
+ *key = buf + k1;
+ *val = buf + i;
+ return 1;
+}
+
+int my_atoi(const char *str)
+{
+ int result = 0;
+ int signal = 1; /* 默认为正数 */
+ if((*str>='0'&&*str<='9')||*str=='-'||*str=='+') {
+ if(*str=='-'||*str=='+') {
+ if(*str=='-')
+ signal = -1; /*输入负数*/
+ str++;
+ }
+ }
+ else
+ return 0;
+ /*开始转换*/
+ while(*str>='0' && *str<='9')
+ result = result*10 + (*str++ - '0' );
+
+ return signal*result;
+}
+
+int isspace(int x)
+{
+ if(x==' '||x=='\t'||x=='\n'||x=='\f'||x=='\b'||x=='\r')
+ return 1;
+ else
+ return 0;
+}
+
+int isdigit(int x)
+{
+ if(x<='9' && x>='0')
+ return 1;
+ else
+ return 0;
+
+}
+
+static long atol(char *nptr)
+{
+ int c; /* current char */
+ long total; /* current total */
+ int sign; /* if ''-'', then negative, otherwise positive */
+ /* skip whitespace */
+ while ( isspace((int)(unsigned char)*nptr) )
+ ++nptr;
+ c = (int)(unsigned char)*nptr++;
+ sign = c; /* save sign indication */
+ if (c == '-' || c == '+')
+ c = (int)(unsigned char)*nptr++; /* skip sign */
+ total = 0;
+ while (isdigit(c)) {
+ total = 10 * total + (c - '0'); /* accumulate digit */
+ c = (int)(unsigned char)*nptr++; /* get next char */
+ }
+ if (sign == '-')
+ return -total;
+ else
+ return total; /* return result, negated if necessary */
+}
+/***
+*int atoi(char *nptr) - Convert string to long
+*
+*Purpose:
+* Converts ASCII string pointed to by nptr to binary.
+* Overflow is not detected. Because of this, we can just use
+* atol().
+*
+*Entry:
+* nptr = ptr to string to convert
+*
+*Exit:
+* return int value of the string
+*
+*Exceptions:
+* None - overflow is not detected.
+*
+*******************************************************************************/
+int atoi(char *nptr)
+{
+ return (int)atol(nptr);
+}
+
diff --git a/drivers/input/touchscreen/ft6x0x/ini.h b/drivers/input/touchscreen/ft6x0x/ini.h
new file mode 100755
index 00000000..72434b53
--- /dev/null
+++ b/drivers/input/touchscreen/ft6x0x/ini.h
@@ -0,0 +1,43 @@
+#ifndef INI_H
+#define INI_H
+
+#define MAX_CFG_BUF 512
+#define SUCCESS 0
+/* return value */
+#define CFG_OK SUCCESS
+#define CFG_SECTION_NOT_FOUND -1
+#define CFG_KEY_NOT_FOUND -2
+#define CFG_ERR -10
+
+#define CFG_ERR_OPEN_FILE -10
+#define CFG_ERR_CREATE_FILE -11
+#define CFG_ERR_READ_FILE -12
+#define CFG_ERR_WRITE_FILE -13
+#define CFG_ERR_FILE_FORMAT -14
+
+
+#define CFG_ERR_EXCEED_BUF_SIZE -22
+
+#define COPYF_OK SUCCESS
+#define COPYF_ERR_OPEN_FILE -10
+#define COPYF_ERR_CREATE_FILE -11
+#define COPYF_ERR_READ_FILE -12
+#define COPYF_ERR_WRITE_FILE -13
+
+
+struct ini_key_location {
+ int ini_section_line_no;
+ int ini_key_line_no;
+ int ini_key_lines;
+};
+
+
+int ini_get_key(char *filedata, char * section, char * key, char * value);
+int ini_get_sections(char *filedata, unsigned char * sections[], int max);
+
+int ini_split_section(char *section, char **name, char **index);
+//int ini_join_section(char **section, char *name, char *index);
+
+int atoi(char *nptr);
+
+#endif