diff options
author | Srikant Patnaik | 2015-01-13 15:08:24 +0530 |
---|---|---|
committer | Srikant Patnaik | 2015-01-13 15:08:24 +0530 |
commit | 97327692361306d1e6259021bc425e32832fdb50 (patch) | |
tree | fe9088f3248ec61e24f404f21b9793cb644b7f01 /drivers/input/touchscreen/icn83xx_ts | |
parent | 2d05a8f663478a44e088d122e0d62109bbc801d0 (diff) | |
parent | a3a8b90b61e21be3dde9101c4e86c881e0f06210 (diff) | |
download | FOSSEE-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/icn83xx_ts')
-rwxr-xr-x | drivers/input/touchscreen/icn83xx_ts/Kconfig | 16 | ||||
-rwxr-xr-x | drivers/input/touchscreen/icn83xx_ts/Makefile | 32 | ||||
-rwxr-xr-x | drivers/input/touchscreen/icn83xx_ts/flash.c | 973 | ||||
-rwxr-xr-x | drivers/input/touchscreen/icn83xx_ts/icn83xx.c | 2034 | ||||
-rwxr-xr-x | drivers/input/touchscreen/icn83xx_ts/icn83xx.h | 434 | ||||
-rwxr-xr-x | drivers/input/touchscreen/icn83xx_ts/icn83xx_fw.h | 3 |
6 files changed, 3492 insertions, 0 deletions
diff --git a/drivers/input/touchscreen/icn83xx_ts/Kconfig b/drivers/input/touchscreen/icn83xx_ts/Kconfig new file mode 100755 index 00000000..dbd6a729 --- /dev/null +++ b/drivers/input/touchscreen/icn83xx_ts/Kconfig @@ -0,0 +1,16 @@ +# +# ICN83XX capacity touch screen driver configuration +# +config TOUCHSCREEN_ICN83XX + tristate "ICN83XX I2C Capacitive Touchscreen Input Driver Support" + depends on ARCH_WMT + default y + 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 s_wmt_ts_icn83xx + diff --git a/drivers/input/touchscreen/icn83xx_ts/Makefile b/drivers/input/touchscreen/icn83xx_ts/Makefile new file mode 100755 index 00000000..e1070854 --- /dev/null +++ b/drivers/input/touchscreen/icn83xx_ts/Makefile @@ -0,0 +1,32 @@ +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_icn83xx
+
+obj-m := $(MY_MODULE_NAME).o
+$(MY_MODULE_NAME)-objs := icn83xx.o flash.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 modules.builtin
+
+clean:
+ rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.order *.symvers modules.builtin
diff --git a/drivers/input/touchscreen/icn83xx_ts/flash.c b/drivers/input/touchscreen/icn83xx_ts/flash.c new file mode 100755 index 00000000..595545d8 --- /dev/null +++ b/drivers/input/touchscreen/icn83xx_ts/flash.c @@ -0,0 +1,973 @@ +/*++
+
+ Copyright (c) 2012-2022 ChipOne Technology (Beijing) Co., Ltd. All Rights Reserved.
+ This PROPRIETARY SOFTWARE is the property of ChipOne Technology (Beijing) Co., Ltd.
+ and may contains trade secrets and/or other confidential information of ChipOne
+ Technology (Beijing) Co., Ltd. This file shall not be disclosed to any third party,
+ in whole or in part, without prior written consent of ChipOne.
+ THIS PROPRIETARY SOFTWARE & ANY RELATED DOCUMENTATION ARE PROVIDED AS IS,
+ WITH ALL FAULTS, & WITHOUT WARRANTY OF ANY KIND. CHIPONE DISCLAIMS ALL EXPRESS OR
+ IMPLIED WARRANTIES.
+
+ File Name: flash.c
+ Abstract:
+ flash operation, read write etc.
+ Author: Zhimin Tian
+ Date : 10 30,2012
+ Version: 0.1[.revision]
+ History :
+ Change logs.
+ --*/
+#include "icn83xx.h"
+
+struct file *fp;
+int g_status = R_OK;
+static char fw_mode = 0;
+static int fw_size = 0;
+static unsigned char *fw_buf;
+
+void icn83xx_rawdatadump(short *mem, int size, char br)
+{
+ int i;
+ for(i=0;i<size; i++)
+ {
+ if((i!=0)&&(i%br == 0))
+ printk("\n");
+ printk(" %5d", mem[i]);
+ }
+ printk("\n");
+}
+
+void icn83xx_memdump(char *mem, int size)
+{
+ int i;
+ for(i=0;i<size; i++)
+ {
+ if(i%16 == 0)
+ printk("\n");
+ printk(" 0x%2x", mem[i]);
+ }
+ printk("\n");
+}
+
+int icn83xx_checksum(int sum, char *buf, unsigned int size)
+{
+ int i;
+ for(i=0; i<size; i++)
+ {
+ sum = sum + buf[i];
+ }
+ return sum;
+}
+
+
+int icn83xx_update_status(int status)
+{
+// flash_info("icn83xx_update_status: %d\n", status);
+ g_status = status;
+ return 0;
+}
+
+int icn83xx_get_status(void)
+{
+ return g_status;
+}
+
+void icn83xx_set_fw(int size, unsigned char *buf)
+{
+ fw_size = size;
+ fw_buf = buf;
+
+}
+
+/***********************************************************************************************
+Name : icn83xx_writeInfo
+Input : addr, value
+Output :
+function : write Flash Info
+***********************************************************************************************/
+
+int icn83xx_writeInfo(unsigned short addr, char value)
+{
+ int ret = -1;
+ char temp_buf[3];
+
+ temp_buf[0] = U16HIBYTE(addr);
+ temp_buf[1] = U16LOBYTE(addr);
+ ret = icn83xx_i2c_txdata(230, temp_buf, 2);
+ if (ret < 0) {
+ op_error("%s failed! ret: %d\n", __func__, ret);
+ return -1;
+ }
+ mdelay(2);
+ temp_buf[0] = value;
+ ret = icn83xx_i2c_txdata(232, temp_buf, 1);
+ if (ret < 0) {
+ op_error("%s failed! ret: %d\n", __func__, ret);
+ return -1;
+ }
+ mdelay(5);
+ return 0;
+}
+/***********************************************************************************************
+Name : icn83xx_readInfo
+Input :
+Output :
+function : read Flash info
+***********************************************************************************************/
+
+int icn83xx_readInfo(unsigned short addr, char *value)
+{
+ int ret = -1;
+ char temp_buf[3];
+
+ temp_buf[0] = U16HIBYTE(addr);
+ temp_buf[1] = U16LOBYTE(addr);
+ ret = icn83xx_i2c_txdata(230, temp_buf, 2);
+ if (ret < 0) {
+ op_error("%s failed! ret: %d\n", __func__, ret);
+ return -1;
+ }
+ mdelay(2);
+ ret = icn83xx_i2c_rxdata(232, value, 1);
+ if (ret < 0) {
+ op_error("%s failed! ret: %d\n", __func__, ret);
+ return -1;
+ }
+ mdelay(2);
+ return 0;
+}
+
+/***********************************************************************************************
+Name : icn83xx_writeReg
+Input : addr, value
+Output :
+function : write MCU xdata and reg
+***********************************************************************************************/
+
+int icn83xx_writeReg(unsigned short addr, char value)
+{
+ int ret = -1;
+ char temp_buf[3];
+
+ temp_buf[0] = U16HIBYTE(addr);
+ temp_buf[1] = U16LOBYTE(addr);
+ ret = icn83xx_i2c_txdata(224, temp_buf, 2);
+ if (ret < 0) {
+ op_error("%s failed! ret: %d\n", __func__, ret);
+ return -1;
+ }
+ mdelay(2);
+ temp_buf[0] = value;
+ ret = icn83xx_i2c_txdata(226, temp_buf, 1);
+ if (ret < 0) {
+ op_error("%s failed! ret: %d\n", __func__, ret);
+ return -1;
+ }
+ mdelay(5);
+ return 0;
+}
+/***********************************************************************************************
+Name : icn83xx_readReg
+Input :
+Output :
+function : read MCU xdata and reg
+***********************************************************************************************/
+
+int icn83xx_readReg(unsigned short addr, char *value)
+{
+ int ret = -1;
+ char temp_buf[3];
+
+ temp_buf[0] = U16HIBYTE(addr);
+ temp_buf[1] = U16LOBYTE(addr);
+ ret = icn83xx_i2c_txdata(224, temp_buf, 2);
+ if (ret < 0) {
+ op_error("%s failed! ret: %d\n", __func__, ret);
+ return -1;
+ }
+ mdelay(2);
+
+ ret = icn83xx_i2c_rxdata(226, value, 1);
+ if (ret < 0) {
+ op_error("%s failed! ret: %d\n", __func__, ret);
+ return -1;
+ }
+ mdelay(2);
+ return 0;
+}
+
+/***********************************************************************************************
+Name : icn83xx_open_fw
+Input : *fw
+
+Output : file size
+function : open the fw file, and return total size
+***********************************************************************************************/
+int icn83xx_open_fw( char *fw)
+{
+ int file_size;
+ mm_segment_t fs;
+ struct inode *inode = NULL;
+ if(strcmp(fw, "icn83xx_firmware") == 0)
+ {
+ fw_mode = 1; //use inner array
+ return fw_size;
+ }
+ else
+ {
+ fw_mode = 0; //use file in file system
+ }
+
+ fp = filp_open(fw, O_RDONLY, 0);
+ if (IS_ERR(fp)) {
+ flash_error("read fw file error\n");
+ return -1;
+ }
+ else
+ flash_info("open fw file ok\n");
+
+ inode = fp->f_dentry->d_inode;
+ file_size = inode->i_size;
+ flash_info("file size: %d\n", file_size);
+
+ fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ return file_size;
+
+}
+
+/***********************************************************************************************
+Name : icn83xx_read_fw
+Input : offset
+ length, read length
+ buf, return buffer
+Output :
+function : read data to buffer
+***********************************************************************************************/
+int icn83xx_read_fw(int offset, int length, char *buf)
+{
+ loff_t pos = offset;
+ if(fw_mode == 1)
+ {
+ memcpy(buf, fw_buf+offset, length);
+ }
+ else
+ {
+ vfs_read(fp, buf, length, &pos);
+ }
+// icn83xx_memdump(buf, length);
+ return 0;
+}
+
+
+/***********************************************************************************************
+Name : icn83xx_close_fw
+Input :
+Output :
+function : close file
+***********************************************************************************************/
+int icn83xx_close_fw(void)
+{
+ if(fw_mode == 0)
+ {
+ filp_close(fp, NULL);
+ }
+
+ return 0;
+}
+/***********************************************************************************************
+Name : icn83xx_readVersion
+Input : void
+Output :
+function : return version
+***********************************************************************************************/
+int icn83xx_readVersion(void)
+{
+ int err = 0;
+ char tmp[2];
+ short CurVersion;
+ err = icn83xx_i2c_rxdata(12, tmp, 2);
+ if (err < 0) {
+ calib_error("%s failed: %d\n", __func__, err);
+ return err;
+ }
+ CurVersion = (tmp[0]<<8) | tmp[1];
+ return CurVersion;
+}
+
+/***********************************************************************************************
+Name : icn83xx_changemode
+Input : normal/factory/config
+Output :
+function : change work mode
+***********************************************************************************************/
+int icn83xx_changemode(char mode)
+{
+ char value = 0x0;
+ icn83xx_write_reg(0, mode);
+ mdelay(1);
+ icn83xx_read_reg(1, &value);
+ while(value != 0)
+ {
+ mdelay(1);
+ icn83xx_read_reg(1, &value);
+ }
+// calib_info("icn83xx_changemode ok\n");
+ return 0;
+}
+
+
+/***********************************************************************************************
+Name : icn83xx_readrawdata
+Input : rownum and length
+Output :
+function : read one row rawdata
+***********************************************************************************************/
+
+int icn83xx_readrawdata(char *buffer, char row, char length)
+{
+ int err = 0;
+ int i;
+// calib_info("readrawdata: %d, length: %d\n", row, length);
+ icn83xx_write_reg(3, row);
+ mdelay(1);
+ err = icn83xx_i2c_rxdata(160, buffer, length);
+ if (err < 0) {
+ calib_error("%s failed: %d\n", __func__, err);
+ return err;
+ }
+
+ for(i=0; i<length; i=i+2)
+ {
+ swap_ab(buffer[i], buffer[i+1]);
+ }
+ return err;
+}
+
+/***********************************************************************************************
+Name : icn83xx_scanTP
+Input :
+Output :
+function : scan one frame rawdata
+***********************************************************************************************/
+
+int icn83xx_scanTP(void)
+{
+ char value = 0;
+ icn83xx_write_reg(2, 0x0);
+ mdelay(1);
+ icn83xx_read_reg(2, &value);
+ while(value != 1)
+ {
+ mdelay(1);
+ icn83xx_read_reg(2, &value);
+ }
+// calib_info("icn83xx_scanTP ok\n");
+ return 0;
+}
+
+/***********************************************************************************************
+Name : icn83xx_readTP
+Input : rownum and columnnum
+Output :
+function : read one frame rawdata
+***********************************************************************************************/
+
+int icn83xx_readTP(char row_num, char column_num, char *buffer)
+{
+ int err = 0;
+ int i;
+// calib_info("icn83xx_readTP\n");
+ icn83xx_changemode(1);
+ icn83xx_scanTP();
+ for(i=0; i<row_num; i++)
+ {
+ icn83xx_readrawdata(&buffer[i*16*2], i, column_num*2);
+ }
+ icn83xx_changemode(0);
+ return err;
+}
+
+
+/***********************************************************************************************
+Name : icn83xx_goto_progmode
+Input :
+Output :
+function : change MCU to progmod
+***********************************************************************************************/
+int icn83xx_goto_progmode(void)
+{
+ int ret = -1;
+// char value[64];
+ char regValue = 0;
+
+ flash_info("icn83xx_goto_progmode\n");
+
+ ret = icn83xx_readReg(0x009, ®Value);
+ if(ret != 0)
+ return ret;
+ flash_info("[0x009]: 0x%x\n", regValue);
+
+// open clock
+ if(regValue != 0xDF)
+ {
+ icn83xx_changemode(2);
+ ret = icn83xx_writeReg(0x002, 0x00);
+ if(ret != 0)
+ return ret;
+ ret = icn83xx_writeReg(0x009, 0xDF);
+ if(ret != 0)
+ return ret;
+ ret = icn83xx_writeReg(0x010, 0x00);
+ if(ret != 0)
+ return ret;
+
+ }
+
+/*
+ addr = 0x0;
+ temp_buf[0] = U16HIBYTE(addr);
+ temp_buf[1] = U16LOBYTE(addr);
+ ret = icn83xx_i2c_txdata(230, temp_buf, 2);
+ if (ret < 0) {
+ pr_err("write reg failed! ret: %d\n", ret);
+ return -1;
+ }
+
+ temp_buf[0] = 0xff;
+ ret = icn83xx_i2c_txdata(232, temp_buf, 1);
+ if (ret < 0) {
+ pr_err("write reg failed! ret: %d\n", ret);
+ return -1;
+ }
+*/
+ ret = icn83xx_writeInfo(0x0, 0xff);
+ if(ret != 0)
+ return ret;
+
+/*
+ addr = 0x1;
+ temp_buf[0] = U16HIBYTE(addr);
+ temp_buf[1] = U16LOBYTE(addr);
+ ret = icn83xx_i2c_txdata(230, temp_buf, 2);
+ if (ret < 0) {
+ pr_err("write reg failed! ret: %d\n", ret);
+ return -1;
+ }
+
+ temp_buf[0] = 0xff;
+ ret = icn83xx_i2c_txdata(232, temp_buf, 1);
+ if (ret < 0) {
+ pr_err("write reg failed! ret: %d\n", ret);
+ return -1;
+ }
+*/
+ ret = icn83xx_writeInfo(0x1, 0xff);
+ if(ret != 0)
+ return ret;
+
+ ret = icn83xx_writeInfo(0x10, 0xff);
+ if(ret != 0)
+ return ret;
+
+ ret = icn83xx_writeInfo(0x11, 0xff);
+ if(ret != 0)
+ return ret;
+/*
+ addr = 0xf00;
+ temp_buf[0] = U16HIBYTE(addr);
+ temp_buf[1] = U16LOBYTE(addr);
+ ret = icn83xx_i2c_txdata(224, temp_buf, 2);
+ if (ret < 0) {
+ pr_err("write reg failed! ret: %d\n", ret);
+ return -1;
+ }
+ temp_buf[0] = 0x1;
+ ret = icn83xx_i2c_txdata(226, temp_buf, 1);
+ if (ret < 0) {
+ pr_err("write reg failed! ret: %d\n", ret);
+ return -1;
+ }
+*/
+ ret = icn83xx_writeReg(0xf00, 1);
+ if(ret != 0)
+ return ret;
+ icn83xx_ts_reset();
+ //mdelay(100);
+ msleep(100);
+ return 0;
+}
+
+/***********************************************************************************************
+Name : icn83xx_check_progmod
+Input :
+Output :
+function : check if MCU at progmode or not
+***********************************************************************************************/
+int icn83xx_check_progmod(void)
+{
+ int ret;
+ unsigned char ucTemp = 0x0;
+ ret = icn83xx_prog_i2c_rxdata(0x0, &ucTemp, 1);
+ flash_info("icn83xx_check_progmod: 0x%x\n", ucTemp);
+ if(ret < 0)
+ {
+ flash_error("icn83xx_check_progmod error, ret: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+
+/***********************************************************************************************
+Name : icn83xx_uu
+Input :
+Output :
+function : unlock flash
+***********************************************************************************************/
+int icn83xx_uu(void)
+{
+ unsigned char ucTemp = 0x0;
+ ucTemp = 0x1e;
+ icn83xx_prog_i2c_txdata(0x050a, &ucTemp, 1);
+ ucTemp = 0x10;
+ icn83xx_prog_i2c_txdata(0x050b, &ucTemp, 1);
+ return 0;
+}
+/***********************************************************************************************
+Name : icn83xx_ll
+Input :
+Output :
+function : lock flash
+***********************************************************************************************/
+void icn83xx_ll(void)
+{
+ unsigned char ucTemp = 0x0;
+ ucTemp = 0xcc;
+ icn83xx_prog_i2c_txdata(0x050a, &ucTemp, 1);
+ ucTemp = 0xcc;
+ icn83xx_prog_i2c_txdata(0x050b, &ucTemp, 1);
+}
+
+/***********************************************************************************************
+Name : icn83xx_op1
+Input :
+Output :
+function : erase flash
+***********************************************************************************************/
+
+int icn83xx_op1(char info, unsigned short offset, unsigned int size)
+{
+ int count = 0;
+ unsigned char ucTemp = 0x0;
+ unsigned short uiAddress = 0x0;
+ int i;
+
+ icn83xx_uu();
+ for(i=0; i<size; )
+ {
+ uiAddress = offset + i;
+// flash_info("uiAddress: 0x%x\n", uiAddress);
+ ucTemp = U16LOBYTE(uiAddress);
+ icn83xx_prog_i2c_txdata(0x0502, &ucTemp, 1);
+ ucTemp = U16HIBYTE(uiAddress);
+ icn83xx_prog_i2c_txdata(0x0503, &ucTemp, 1);
+
+ ucTemp = 0x02;
+ icn83xx_prog_i2c_txdata(0x0500, &ucTemp, 1);
+ ucTemp = 0x01;
+ count = 0;
+ while(ucTemp)
+ {
+ icn83xx_prog_i2c_rxdata(0x0501, &ucTemp, 1);
+ count++;
+ if(count > 5000)
+ {
+ flash_error("op1 ucTemp: 0x%x\n", ucTemp);
+ return 1;
+ }
+ }
+ i = i+1024;
+ }
+ icn83xx_ll();
+ return 0;
+}
+
+/***********************************************************************************************
+Name : icn83xx_op2
+Input :
+Output :
+function : progm flash
+***********************************************************************************************/
+int icn83xx_op2(char info, unsigned short offset, unsigned char * buffer, unsigned int size)
+{
+ int count = 0;
+ unsigned int flash_size;
+ unsigned char ucTemp;
+ unsigned short uiAddress;
+ ucTemp = 0x00;
+ uiAddress = 0x1000;
+
+ icn83xx_prog_i2c_txdata(uiAddress, buffer, size);
+
+ icn83xx_uu();
+
+ ucTemp = U16LOBYTE(offset);
+ icn83xx_prog_i2c_txdata(0x0502, &ucTemp, 1);
+ ucTemp = U16HIBYTE(offset);
+ icn83xx_prog_i2c_txdata(0x0503, &ucTemp, 1);
+
+ icn83xx_prog_i2c_txdata(0x0504, (char *)&uiAddress, 2);
+
+
+//ensure size is even
+ if(size%2 != 0)
+ {
+ flash_info("write op size: %d\n", size);
+ flash_size = size+1;
+ }
+ else
+ flash_size = size;
+
+ ucTemp = U16LOBYTE(flash_size);
+ icn83xx_prog_i2c_txdata(0x0506, &ucTemp, 1);
+ ucTemp = U16HIBYTE(flash_size);
+ icn83xx_prog_i2c_txdata(0x0507, &ucTemp, 1);
+ ucTemp = 0x01;
+
+ if(info > 0)
+ ucTemp = 0x01 | (1<<3);
+
+ icn83xx_prog_i2c_txdata(0x0500, &ucTemp, 1); //
+ while(ucTemp)
+ {
+ icn83xx_prog_i2c_rxdata(0x0501, &ucTemp, 1);
+ count++;
+ if(count > 5000)
+ {
+ flash_error("op2 ucTemp: 0x%x\n", ucTemp);
+ return 1;
+ }
+
+ }
+ icn83xx_ll();
+ return 0;
+}
+
+/***********************************************************************************************
+Name : icn83xx_op3
+Input :
+Output :
+function : read flash
+***********************************************************************************************/
+int icn83xx_op3(char info, unsigned short offset, unsigned char * buffer, unsigned int size)
+{
+ int count = 0;
+ unsigned int flash_size;
+ unsigned char ucTemp;
+ unsigned short uiAddress;
+ ucTemp = 0x00;
+ uiAddress = 0x1000;
+ icn83xx_uu();
+ ucTemp = U16LOBYTE(offset);
+ icn83xx_prog_i2c_txdata(0x0502, &ucTemp, 1);
+ ucTemp = U16HIBYTE(offset);
+ icn83xx_prog_i2c_txdata(0x0503, &ucTemp, 1);
+
+ icn83xx_prog_i2c_txdata(0x0504, (unsigned char*)&uiAddress, 2);
+
+//ensure size is even
+ if(size%2 != 0)
+ {
+ flash_info("read op size: %d\n", size);
+ flash_size = size+1;
+ }
+ else
+ flash_size = size;
+
+ ucTemp = U16LOBYTE(flash_size);
+ icn83xx_prog_i2c_txdata(0x0506, &ucTemp, 1);
+
+ ucTemp = U16HIBYTE(flash_size);
+ icn83xx_prog_i2c_txdata(0x0507, &ucTemp, 1);
+ ucTemp = 0x40;
+
+ if(info > 0)
+ ucTemp = 0x40 | (1<<3);
+
+ icn83xx_prog_i2c_txdata(0x0500, &ucTemp, 1);
+ ucTemp = 0x01;
+ while(ucTemp)
+ {
+ icn83xx_prog_i2c_rxdata(0x0501, &ucTemp, 1);
+ count++;
+ if(count > 5000)
+ {
+ flash_error("op3 ucTemp: 0x%x\n", ucTemp);
+ return 1;
+ }
+
+ }
+ icn83xx_ll();
+ icn83xx_prog_i2c_rxdata(uiAddress, buffer, size);
+ return 0;
+}
+
+
+/***********************************************************************************************
+Name : icn83xx_goto_nomalmode
+Input :
+Output :
+function : when prog flash ok, change flash info flag
+***********************************************************************************************/
+int icn83xx_goto_nomalmode(void)
+{
+ int ret = -1;
+ //unsigned short addr = 0;
+ char temp_buf[3];
+
+ flash_info("icn83xx_goto_nomalmode\n");
+ temp_buf[0] = 0x03;
+ icn83xx_prog_i2c_txdata(0x0f00, temp_buf, 1);
+
+ msleep(100);
+/*
+ addr = 0;
+ temp_buf[0] = U16HIBYTE(addr);
+ temp_buf[1] = U16LOBYTE(addr);
+ temp_buf[2] = 0;
+ ret = icn83xx_i2c_txdata(230, temp_buf, 2);
+ if (ret < 0) {
+ pr_err("write reg failed! ret: %d\n", ret);
+ return -1;
+ }
+
+ icn83xx_i2c_rxdata(232, &temp_buf[2], 1);
+ flash_info("temp_buf[2]: 0x%x\n", temp_buf[2]);
+*/
+ ret = icn83xx_readInfo(0, &temp_buf[2]);
+ if(ret != 0)
+ return ret;
+ flash_info("temp_buf[2]: 0x%x\n", temp_buf[2]);
+ if(temp_buf[2] == 0xff)
+ {
+/*
+ addr = 0;
+ temp_buf[0] = U16HIBYTE(addr);
+ temp_buf[1] = U16LOBYTE(addr);
+ ret = icn83xx_i2c_txdata(230, temp_buf, 2);
+ if (ret < 0) {
+ pr_err("write reg failed! ret: %d\n", ret);
+ return -1;
+ }
+ temp_buf[0] = 0x11;
+ ret = icn83xx_i2c_txdata(232, temp_buf, 1);
+ if (ret < 0) {
+ pr_err("write reg failed! ret: %d\n", ret);
+ return -1;
+ }
+*/
+ ret = icn83xx_writeInfo(0, 0x11);
+ if(ret != 0)
+ return ret;
+
+ }
+ return 0;
+}
+
+/***********************************************************************************************
+Name : icn83xx_read_fw_Ver
+Input : fw
+Output :
+function : read fw version
+***********************************************************************************************/
+
+short icn83xx_read_fw_Ver(char *fw)
+{
+ short FWversion;
+ char tmp[2];
+ int file_size;
+ file_size = icn83xx_open_fw(fw);
+ if(file_size < 0)
+ {
+ return -1;
+ }
+ icn83xx_read_fw(0x4000, 2, &tmp[0]);
+
+ icn83xx_close_fw();
+ FWversion = (tmp[0]<<8)|tmp[1];
+// flash_info("FWversion: 0x%x\n", FWversion);
+ return FWversion;
+}
+
+
+
+
+/***********************************************************************************************
+Name : icn83xx_fw_update
+Input : fw
+Output :
+function : upgrade fw
+***********************************************************************************************/
+
+E_UPGRADE_ERR_TYPE icn83xx_fw_update(char *fw)
+{
+ int file_size, last_length;
+ int j, num;
+ int checksum_bak = 0;
+ int checksum = 0;
+ char temp_buf[B_SIZE];
+#ifdef ENABLE_BYTE_CHECK
+ char temp_buf1[B_SIZE];
+#endif
+
+ file_size = icn83xx_open_fw(fw);
+ if(file_size < 0)
+ {
+ icn83xx_update_status(R_FILE_ERR);
+ return R_FILE_ERR;
+ }
+
+ if(icn83xx_goto_progmode() != 0)
+ {
+ if(icn83xx_check_progmod() < 0)
+ {
+ icn83xx_update_status(R_STATE_ERR);
+ icn83xx_close_fw();
+ return R_STATE_ERR;
+ }
+ }
+// msleep(50);
+
+ if(icn83xx_op1(0, 0, file_size) != 0)
+ {
+ flash_error("icn83xx_op1 error\n");
+ icn83xx_update_status(R_ERASE_ERR);
+ icn83xx_close_fw();
+ return R_ERASE_ERR;
+ }
+ icn83xx_update_status(5);
+
+ num = file_size/B_SIZE;
+ for(j=0; j < num; j++)
+ {
+ icn83xx_read_fw(j*B_SIZE, B_SIZE, temp_buf);
+
+// icn83xx_op3(0, j*B_SIZE, temp_buf1, B_SIZE);
+// icn83xx_memdump(temp_buf1, B_SIZE);
+
+ if(icn83xx_op2(0, j*B_SIZE, temp_buf, B_SIZE) != 0)
+ {
+ icn83xx_update_status(R_PROGRAM_ERR);
+ icn83xx_close_fw();
+ return R_PROGRAM_ERR;
+ }
+ checksum_bak = icn83xx_checksum(checksum_bak, temp_buf, B_SIZE);
+
+ icn83xx_update_status(5+(int)(60*j/num));
+ }
+ last_length = file_size - B_SIZE*j;
+ if(last_length > 0)
+ {
+ icn83xx_read_fw(j*B_SIZE, last_length, temp_buf);
+
+// icn83xx_op3(0, j*B_SIZE, temp_buf1, B_SIZE);
+// icn83xx_memdump(temp_buf1, B_SIZE);
+
+ if(icn83xx_op2(0, j*B_SIZE, temp_buf, last_length) != 0)
+ {
+ icn83xx_update_status(R_PROGRAM_ERR);
+ icn83xx_close_fw();
+ return R_PROGRAM_ERR;
+ }
+ checksum_bak = icn83xx_checksum(checksum_bak, temp_buf, last_length);
+ }
+
+ icn83xx_close_fw();
+ icn83xx_update_status(65);
+
+#ifdef ENABLE_BYTE_CHECK
+ file_size = icn83xx_open_fw(fw);
+ num = file_size/B_SIZE;
+#endif
+
+ for(j=0; j < num; j++)
+ {
+
+#ifdef ENABLE_BYTE_CHECK
+ icn83xx_read_fw(j*B_SIZE, B_SIZE, temp_buf1);
+#endif
+ icn83xx_op3(0, j*B_SIZE, temp_buf, B_SIZE);
+ checksum = icn83xx_checksum(checksum, temp_buf, B_SIZE);
+
+#ifdef ENABLE_BYTE_CHECK
+ if(memcmp(temp_buf1, temp_buf, B_SIZE) != 0)
+ {
+ flash_error("cmp error, %d\n", j);
+ icn83xx_memdump(temp_buf1, B_SIZE);
+ icn83xx_memdump(temp_buf, B_SIZE);
+ icn83xx_update_status(R_VERIFY_ERR);
+#ifdef ENABLE_BYTE_CHECK
+ icn83xx_close_fw();
+#endif
+ return R_VERIFY_ERR;
+ //while(1);
+ }
+#endif
+ icn83xx_update_status(65+(int)(30*j/num));
+ }
+
+#ifdef ENABLE_BYTE_CHECK
+ last_length = file_size - B_SIZE*j;
+#endif
+ if(last_length > 0)
+ {
+#ifdef ENABLE_BYTE_CHECK
+ icn83xx_read_fw(j*B_SIZE, last_length, temp_buf1);
+#endif
+ icn83xx_op3(0, j*B_SIZE, temp_buf, last_length);
+ checksum = icn83xx_checksum(checksum, temp_buf, last_length);
+
+#ifdef ENABLE_BYTE_CHECK
+ if(memcmp(temp_buf1, temp_buf, last_length) != 0)
+ {
+ flash_error("cmp error, %d\n", j);
+ icn83xx_memdump(temp_buf1, last_length);
+ icn83xx_memdump(temp_buf, last_length);
+ icn83xx_update_status(R_VERIFY_ERR);
+#ifdef ENABLE_BYTE_CHECK
+ icn83xx_close_fw();
+#endif
+ return R_VERIFY_ERR;
+ //while(1);
+ }
+#endif
+
+ }
+
+#ifdef ENABLE_BYTE_CHECK
+ icn83xx_close_fw();
+#endif
+
+ flash_info("checksum_bak: 0x%x, checksum: 0x%x\n", checksum_bak, checksum);
+ if(checksum_bak != checksum)
+ {
+ flash_error("upgrade checksum error\n");
+ icn83xx_update_status(R_VERIFY_ERR);
+ return R_VERIFY_ERR;
+ }
+
+ if(icn83xx_goto_nomalmode() != 0)
+ {
+ flash_error("icn83xx_goto_nomalmode error\n");
+ icn83xx_update_status(R_STATE_ERR);
+ return R_STATE_ERR;
+ }
+
+ icn83xx_update_status(R_OK);
+ flash_info("upgrade ok\n");
+ return R_OK;
+}
diff --git a/drivers/input/touchscreen/icn83xx_ts/icn83xx.c b/drivers/input/touchscreen/icn83xx_ts/icn83xx.c new file mode 100755 index 00000000..60e42e50 --- /dev/null +++ b/drivers/input/touchscreen/icn83xx_ts/icn83xx.c @@ -0,0 +1,2034 @@ +/*++ + + Copyright (c) 2012-2022 ChipOne Technology (Beijing) Co., Ltd. All Rights Reserved. + This PROPRIETARY SOFTWARE is the property of ChipOne Technology (Beijing) Co., Ltd. + and may contains trade secrets and/or other confidential information of ChipOne + Technology (Beijing) Co., Ltd. This file shall not be disclosed to any third party, + in whole or in part, without prior written consent of ChipOne. + THIS PROPRIETARY SOFTWARE & ANY RELATED DOCUMENTATION ARE PROVIDED AS IS, + WITH ALL FAULTS, & WITHOUT WARRANTY OF ANY KIND. CHIPONE DISCLAIMS ALL EXPRESS OR + IMPLIED WARRANTIES. + + File Name: icn83xx.c +Abstract: +input driver. +Author: Zhimin Tian +Date : 01,17,2013 +Version: 1.0 +History : +2012,10,30, V0.1 first version +--*/ + +#include "icn83xx.h" + +#if COMPILE_FW_WITH_DRIVER +#include "icn83xx_fw.h" +#endif + +static struct touch_param g_param; +static struct i2c_client *this_client; +short log_rawdata[28][16];// = {0,}; +short log_diffdata[28][16];// = {0,}; +static int l_suspend = 0; // 1:suspend, 0:normal state + +#if SUPPORT_ROCKCHIP +//if file system not ready,you can use inner array +//static char firmware[128] = "icn83xx_firmware"; +#endif +static char firmware[128] = {"/system/etc/firmware/fw.bin"}; + +//static void icn_delayedwork_fun(struct work_struct *work); +extern int register_bl_notifier(struct notifier_block *nb); +extern int unregister_bl_notifier(struct notifier_block *nb); +extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen); + +#define dbg(fmt, args...) do{if (g_param.dbg) printk(KERN_ALERT "[%s]: " fmt, __FUNCTION__ , ## args);}while(0) + +static ssize_t cat_dbg(struct device *dev, struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "echo 1 > dbg : print debug message.\necho 0 > dbg : Do not print debug message.\n"); +} +static ssize_t echo_dbg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + g_param.dbg = simple_strtoul(buf, NULL, 10) ? 1 : 0; + return count; +} +static DEVICE_ATTR(dbg, S_IRUGO | S_IWUSR, cat_dbg, echo_dbg); + +#if SUPPORT_SYSFS +static enum hrtimer_restart chipone_timer_func(struct hrtimer *timer); +static ssize_t icn83xx_show_update(struct device* cd,struct device_attribute *attr, char* buf); +static ssize_t icn83xx_store_update(struct device* cd, struct device_attribute *attr, const char* buf, size_t len); +static ssize_t icn83xx_show_process(struct device* cd,struct device_attribute *attr, char* buf); +static ssize_t icn83xx_store_process(struct device* cd, struct device_attribute *attr,const char* buf, size_t len); + +static DEVICE_ATTR(update, S_IRUGO | S_IWUSR, icn83xx_show_update, icn83xx_store_update); +static DEVICE_ATTR(process, S_IRUGO | S_IWUSR, icn83xx_show_process, icn83xx_store_process); + +static ssize_t icn83xx_show_process(struct device* cd,struct device_attribute *attr, char* buf) +{ + ssize_t ret = 0; + sprintf(buf, "icn83xx process\n"); + ret = strlen(buf) + 1; + return ret; +} + +static ssize_t icn83xx_store_process(struct device* cd, struct device_attribute *attr, + const char* buf, size_t len) +{ + struct icn83xx_ts_data *icn83xx_ts = i2c_get_clientdata(this_client); + unsigned long on_off = simple_strtoul(buf, NULL, 10); + if(on_off == 0) + { + icn83xx_ts->work_mode = on_off; + } + else if((on_off == 1) || (on_off == 2)) + { + if((icn83xx_ts->work_mode == 0) && (icn83xx_ts->use_irq == 1)) + { + hrtimer_init(&icn83xx_ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + icn83xx_ts->timer.function = chipone_timer_func; + hrtimer_start(&icn83xx_ts->timer, ktime_set(CTP_START_TIMER/1000, (CTP_START_TIMER%1000)*1000000), HRTIMER_MODE_REL); + } + icn83xx_ts->work_mode = on_off; + } + return len; +} + +static ssize_t icn83xx_show_update(struct device* cd, + struct device_attribute *attr, char* buf) +{ + ssize_t ret = 0; + sprintf(buf, "icn83xx firmware\n"); + ret = strlen(buf) + 1; + return ret; +} + +static ssize_t icn83xx_store_update(struct device* cd, struct device_attribute *attr, const char* buf, size_t len) +{ + //int err=0; + //unsigned long on_off = simple_strtoul(buf, NULL, 10); + return len; +} + +static int icn83xx_create_sysfs(struct i2c_client *client) +{ + int err; + struct device *dev = &(client->dev); + icn83xx_trace("%s: \n",__func__); + err = device_create_file(dev, &dev_attr_update); + err = device_create_file(dev, &dev_attr_process); + return err; +} + +#endif + +#if SUPPORT_PROC_FS + +pack_head cmd_head; +static struct proc_dir_entry *icn83xx_proc_entry; +int DATA_LENGTH = 0; +static int icn83xx_tool_write(struct file *filp, const char __user *buff, unsigned long len, void *data) +{ + int ret = 0; + + struct icn83xx_ts_data *icn83xx_ts = i2c_get_clientdata(this_client); + proc_info("%s \n",__func__); + if(down_interruptible(&icn83xx_ts->sem)) + { + return -1; + } + ret = copy_from_user(&cmd_head, buff, CMD_HEAD_LENGTH); + if(ret) + { + proc_error("copy_from_user failed.\n"); + goto write_out; + } + else + { + ret = CMD_HEAD_LENGTH; + } + + proc_info("wr :0x%02x.\n", cmd_head.wr); + proc_info("flag:0x%02x.\n", cmd_head.flag); + proc_info("circle :%d.\n", (int)cmd_head.circle); + proc_info("times :%d.\n", (int)cmd_head.times); + proc_info("retry :%d.\n", (int)cmd_head.retry); + proc_info("data len:%d.\n", (int)cmd_head.data_len); + proc_info("addr len:%d.\n", (int)cmd_head.addr_len); + proc_info("addr:0x%02x%02x.\n", cmd_head.addr[0], cmd_head.addr[1]); + proc_info("len:%d.\n", (int)len); + proc_info("data:0x%02x%02x.\n", buff[CMD_HEAD_LENGTH], buff[CMD_HEAD_LENGTH+1]); + if (1 == cmd_head.wr) // write iic + { + if(1 == cmd_head.addr_len) + { + ret = copy_from_user(&cmd_head.data[0], &buff[CMD_HEAD_LENGTH], cmd_head.data_len); + if(ret) + { + proc_error("copy_from_user failed.\n"); + goto write_out; + } + ret = icn83xx_i2c_txdata(cmd_head.addr[0], &cmd_head.data[0], cmd_head.data_len); + if (ret < 0) { + proc_error("write iic failed! ret: %d\n", ret); + goto write_out; + } + ret = cmd_head.data_len + CMD_HEAD_LENGTH; + goto write_out; + } + } + else if(3 == cmd_head.wr) + { + ret = copy_from_user(&cmd_head.data[0], &buff[CMD_HEAD_LENGTH], cmd_head.data_len); + if(ret) + { + proc_error("copy_from_user failed.\n"); + goto write_out; + } + ret = cmd_head.data_len + CMD_HEAD_LENGTH; + memset(firmware, 0, 128); + memcpy(firmware, &cmd_head.data[0], cmd_head.data_len); + proc_info("firmware : %s\n", firmware); + } + else if(5 == cmd_head.wr) + { + icn83xx_update_status(1); + ret = kernel_thread((int (*)(void *))icn83xx_fw_update,firmware,CLONE_KERNEL); + icn83xx_trace("the kernel_thread result is:%d\n", ret); + } + else if(7 == cmd_head.wr) //write reg + { + if(2 == cmd_head.addr_len) + { + ret = copy_from_user(&cmd_head.data[0], &buff[CMD_HEAD_LENGTH], cmd_head.data_len); + if(ret) + { + proc_error("copy_from_user failed.\n"); + goto write_out; + } + ret = icn83xx_writeReg((cmd_head.addr[0]<<8)|cmd_head.addr[1], cmd_head.data[0]); + if (ret < 0) { + proc_error("write reg failed! ret: %d\n", ret); + goto write_out; + } + ret = cmd_head.data_len + CMD_HEAD_LENGTH; + goto write_out; + + } + } + +write_out: + up(&icn83xx_ts->sem); + return len; + +} +static int icn83xx_tool_read( char *page, char **start, off_t off, int count, int *eof, void *data ) +{ + int i; + int ret = 0; + int data_len = 0; + int len = 0; + int loc = 0; + char retvalue; + struct icn83xx_ts_data *icn83xx_ts = i2c_get_clientdata(this_client); + if(down_interruptible(&icn83xx_ts->sem)) + { + return -1; + } + proc_info("%s: count:%d, off:%d, cmd_head.data_len: %d\n",__func__, count, (int)off, cmd_head.data_len); + if (cmd_head.wr % 2) + { + ret = 0; + goto read_out; + } + else if (0 == cmd_head.wr) //read iic + { + if(1 == cmd_head.addr_len) + { + data_len = cmd_head.data_len; + if(cmd_head.addr[0] == 0xff) + { + page[0] = 83; + proc_info("read ic type: %d\n", page[0]); + } + else + { + while(data_len>0) + { + if (data_len > DATA_LENGTH) + { + len = DATA_LENGTH; + } + else + { + len = data_len; + } + data_len -= len; + memset(&cmd_head.data[0], 0, len+1); + ret = icn83xx_i2c_rxdata(cmd_head.addr[0]+loc, &cmd_head.data[0], len); + //proc_info("cmd_head.data[0]: 0x%02x\n", cmd_head.data[0]); + //proc_info("cmd_head.data[1]: 0x%02x\n", cmd_head.data[1]); + if(ret < 0) + { + icn83xx_error("read iic failed: %d\n", ret); + goto read_out; + } + else + { + //proc_info("iic read out %d bytes, loc: %d\n", len, loc); + memcpy(&page[loc], &cmd_head.data[0], len); + } + loc += len; + } + proc_info("page[0]: 0x%02x\n", page[0]); + proc_info("page[1]: 0x%02x\n", page[1]); + } + } + } + else if(2 == cmd_head.wr) //read rawdata + { + //scan tp rawdata + icn83xx_write_reg(4, 0x20); + mdelay(cmd_head.times); + icn83xx_read_reg(2, &retvalue); + while(retvalue != 1) + { + mdelay(cmd_head.times); + icn83xx_read_reg(2, &retvalue); + } + + if(2 == cmd_head.addr_len) + { + for(i=0; i<cmd_head.addr[1]; i++) + { + icn83xx_write_reg(3, i); + mdelay(cmd_head.times); + ret = icn83xx_i2c_rxdata(128, &cmd_head.data[0], cmd_head.addr[0]*2); + if (ret < 0) + { + icn83xx_error("read rawdata failed: %d\n", ret); + goto read_out; + } + else + { + //proc_info("read rawdata out %d bytes, loc: %d\n", cmd_head.addr[0]*2, loc); + memcpy(&page[loc], &cmd_head.data[0], cmd_head.addr[0]*2); + } + loc += cmd_head.addr[0]*2; + } + for(i=0; i<cmd_head.data_len; i=i+2) + { + swap_ab(page[i], page[i+1]); + } + //icn83xx_rawdatadump(&page[0], cmd_head.data_len/2, cmd_head.addr[0]); + } + + //finish scan tp rawdata + icn83xx_write_reg(2, 0x0); + + } + else if(4 == cmd_head.wr) //get update status + { + page[0] = icn83xx_get_status(); + } + else if(6 == cmd_head.wr) //read reg + { + if(2 == cmd_head.addr_len) + { + ret = icn83xx_readReg((cmd_head.addr[0]<<8)|cmd_head.addr[1], &cmd_head.data[0]); + if (ret < 0) { + proc_error("reg reg failed! ret: %d\n", ret); + goto read_out; + } + page[0] = cmd_head.data[0]; + goto read_out; + } + } +read_out: + up(&icn83xx_ts->sem); + proc_info("%s out: %d, cmd_head.data_len: %d\n\n",__func__, count, cmd_head.data_len); + return cmd_head.data_len; +} + +int init_proc_node(void) +{ + int i; + memset(&cmd_head, 0, sizeof(cmd_head)); + cmd_head.data = NULL; + + i = 5; + while ((!cmd_head.data) && i) + { + cmd_head.data = kzalloc(i * DATA_LENGTH_UINT, GFP_KERNEL); + if (NULL != cmd_head.data) + { + break; + } + i--; + } + if (i) + { + //DATA_LENGTH = i * DATA_LENGTH_UINT + GTP_ADDR_LENGTH; + DATA_LENGTH = i * DATA_LENGTH_UINT; + icn83xx_trace("alloc memory size:%d.\n", DATA_LENGTH); + } + else + { + proc_error("alloc for memory failed.\n"); + return 0; + } + + icn83xx_proc_entry = create_proc_entry(ICN83XX_ENTRY_NAME, 0666, NULL); + if (icn83xx_proc_entry == NULL) + { + proc_error("Couldn't create proc entry!\n"); + return 0; + } + else + { + icn83xx_trace("Create proc entry success!\n"); + icn83xx_proc_entry->write_proc = icn83xx_tool_write; + icn83xx_proc_entry->read_proc = icn83xx_tool_read; + } + + return 1; +} + +void uninit_proc_node(void) +{ + kfree(cmd_head.data); + cmd_head.data = NULL; + remove_proc_entry(ICN83XX_ENTRY_NAME, NULL); +} + +#endif + + +#if TOUCH_VIRTUAL_KEYS +static ssize_t virtual_keys_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf, + __stringify(EV_KEY) ":" __stringify(KEY_MENU) ":100:1030:50:60" + ":" __stringify(EV_KEY) ":" __stringify(KEY_HOME) ":280:1030:50:60" + ":" __stringify(EV_KEY) ":" __stringify(KEY_BACK) ":470:1030:50:60" + ":" __stringify(EV_KEY) ":" __stringify(KEY_SEARCH) ":900:1030:50:60" + "\n"); +} + +static struct kobj_attribute virtual_keys_attr = { + .attr = { + .name = "virtualkeys.chipone-ts", + .mode = S_IRUGO, + }, + .show = &virtual_keys_show, +}; + +static struct attribute *properties_attrs[] = { + &virtual_keys_attr.attr, + NULL +}; + +static struct attribute_group properties_attr_group = { + .attrs = properties_attrs, +}; + +static void icn83xx_ts_virtual_keys_init(void) +{ + int ret = 0; + struct kobject *properties_kobj; + properties_kobj = kobject_create_and_add("board_properties", NULL); + if (properties_kobj) + ret = sysfs_create_group(properties_kobj, + &properties_attr_group); + if (!properties_kobj || ret) + pr_err("failed to create board_properties\n"); +} +#endif + + +/* --------------------------------------------------------------------- + * + * Chipone panel related driver + * + * + ----------------------------------------------------------------------*/ +/*********************************************************************************************** +Name : icn83xx_ts_wakeup +Input : void +Output : ret +function : this function is used to wakeup tp + ***********************************************************************************************/ +void icn83xx_ts_wakeup(void) +{ + //#if def TOUCH_RESET_PIN + +} + +/*********************************************************************************************** +Name : icn83xx_ts_reset +Input : void +Output : ret +function : this function is used to reset tp, you should not delete it + ***********************************************************************************************/ +void icn83xx_ts_reset(void) +{ + int rst = g_param.rstgpio; + gpio_direction_output(rst, 0); + //mdelay(30); + msleep(50); + gpio_direction_output(rst, 1); + //mdelay(50); + msleep(50); + +} + +/*********************************************************************************************** +Name : icn83xx_irq_disable +Input : void +Output : ret +function : this function is used to disable irq + ***********************************************************************************************/ +void icn83xx_irq_disable(void) +{ + unsigned long irqflags; + struct icn83xx_ts_data *icn83xx_ts = i2c_get_clientdata(this_client); + + spin_lock_irqsave(&icn83xx_ts->irq_lock, irqflags); + if (!icn83xx_ts->irq_is_disable) + { + icn83xx_ts->irq_is_disable = 1; + wmt_gpio_mask_irq(g_param.irqgpio); + //disable_irq_nosync(icn83xx_ts->irq); + //disable_irq(icn83xx_ts->irq); + } + spin_unlock_irqrestore(&icn83xx_ts->irq_lock, irqflags); +} + +/*********************************************************************************************** +Name : icn83xx_irq_enable +Input : void +Output : ret +function : this function is used to enable irq + ***********************************************************************************************/ +void icn83xx_irq_enable(void) +{ + unsigned long irqflags = 0; + struct icn83xx_ts_data *icn83xx_ts = i2c_get_clientdata(this_client); + + spin_lock_irqsave(&icn83xx_ts->irq_lock, irqflags); + if (icn83xx_ts->irq_is_disable) + { + wmt_gpio_unmask_irq(g_param.irqgpio); + //enable_irq(icn83xx_ts->irq); + icn83xx_ts->irq_is_disable = 0; + } + spin_unlock_irqrestore(&icn83xx_ts->irq_lock, irqflags); + +} + +/*********************************************************************************************** +Name : icn83xx_prog_i2c_rxdata +Input : addr + *rxdata + length +Output : ret +function : read data from icn83xx, prog mode + ***********************************************************************************************/ +int icn83xx_prog_i2c_rxdata(unsigned short addr, char *rxdata, int length) +{ + int ret = -1; + int retries = 0; +#if 0 + struct i2c_msg msgs[] = { + { + .addr = ICN83XX_PROG_IIC_ADDR,//this_client->addr, + .flags = I2C_M_RD, + .len = length, + .buf = rxdata, +#if SUPPORT_ROCKCHIP + .scl_rate = ICN83XX_I2C_SCL, +#endif + }, + }; + + icn83xx_prog_i2c_txdata(addr, NULL, 0); + while(retries < IIC_RETRY_NUM) + { + ret = i2c_transfer(this_client->adapter, msgs, 1); + if(ret == 1)break; + retries++; + } + if (retries >= IIC_RETRY_NUM) + { + icn83xx_error("%s i2c read error: %d\n", __func__, ret); + // icn83xx_ts_reset(); + } +#else + unsigned char tmp_buf[2]; + struct i2c_msg msgs[] = { + { + .addr = ICN83XX_PROG_IIC_ADDR,//this_client->addr, + .flags = 0, + .len = 2, + .buf = tmp_buf, +#if SUPPORT_ROCKCHIP + .scl_rate = ICN83XX_I2C_SCL, +#endif + }, + { + .addr = ICN83XX_PROG_IIC_ADDR,//this_client->addr, + .flags = I2C_M_RD, + .len = length, + .buf = rxdata, +#if SUPPORT_ROCKCHIP + .scl_rate = ICN83XX_I2C_SCL, +#endif + }, + }; + tmp_buf[0] = U16HIBYTE(addr); + tmp_buf[1] = U16LOBYTE(addr); + + while(retries < IIC_RETRY_NUM) + { + ret = i2c_transfer(this_client->adapter, msgs, 2); + if(ret == 2)break; + retries++; + } + + if (retries >= IIC_RETRY_NUM) + { + icn83xx_error("%s i2c read error: %d\n", __func__, ret); + // icn83xx_ts_reset(); + } +#endif + return ret; +} +/*********************************************************************************************** +Name : icn83xx_prog_i2c_txdata +Input : addr + *rxdata + length +Output : ret +function : send data to icn83xx , prog mode + ***********************************************************************************************/ +int icn83xx_prog_i2c_txdata(unsigned short addr, char *txdata, int length) +{ + int ret = -1; + char tmp_buf[128]; + int retries = 0; + struct i2c_msg msg[] = { + { + .addr = ICN83XX_PROG_IIC_ADDR,//this_client->addr, + .flags = 0, + .len = length + 2, + .buf = tmp_buf, +#if SUPPORT_ROCKCHIP + .scl_rate = ICN83XX_I2C_SCL, +#endif + }, + }; + + if (length > 125) + { + icn83xx_error("%s too big datalen = %d!\n", __func__, length); + return -1; + } + + tmp_buf[0] = U16HIBYTE(addr); + tmp_buf[1] = U16LOBYTE(addr); + + if (length != 0 && txdata != NULL) + { + memcpy(&tmp_buf[2], txdata, length); + } + + while(retries < IIC_RETRY_NUM) + { + ret = i2c_transfer(this_client->adapter, msg, 1); + if(ret == 1)break; + retries++; + } + + if (retries >= IIC_RETRY_NUM) + { + icn83xx_error("%s i2c write error: %d\n", __func__, ret); + // icn83xx_ts_reset(); + } + return ret; +} +/*********************************************************************************************** +Name : icn83xx_prog_write_reg +Input : addr -- address +para -- parameter +Output : +function : write register of icn83xx, prog mode + ***********************************************************************************************/ +int icn83xx_prog_write_reg(unsigned short addr, char para) +{ + char buf[3]; + int ret = -1; + + buf[0] = para; + ret = icn83xx_prog_i2c_txdata(addr, buf, 1); + if (ret < 0) { + icn83xx_error("write reg failed! %#x ret: %d\n", buf[0], ret); + return -1; + } + + return ret; +} + + +/*********************************************************************************************** +Name : icn83xx_prog_read_reg +Input : addr +pdata +Output : +function : read register of icn83xx, prog mode + ***********************************************************************************************/ +int icn83xx_prog_read_reg(unsigned short addr, char *pdata) +{ + int ret = -1; + ret = icn83xx_prog_i2c_rxdata(addr, pdata, 1); + return ret; +} + +/*********************************************************************************************** +Name : icn83xx_i2c_rxdata +Input : addr + *rxdata + length +Output : ret +function : read data from icn83xx, normal mode + ***********************************************************************************************/ +int icn83xx_i2c_rxdata(unsigned char addr, char *rxdata, int length) +{ + int ret = -1; + int retries = 0; +#if 0 + struct i2c_msg msgs[] = { + { + .addr = this_client->addr, + .flags = I2C_M_RD, + .len = length, + .buf = rxdata, +#if SUPPORT_ROCKCHIP + .scl_rate = ICN83XX_I2C_SCL, +#endif + }, + }; + + icn83xx_i2c_txdata(addr, NULL, 0); + while(retries < IIC_RETRY_NUM) + { + + ret = i2c_transfer(this_client->adapter, msgs, 1); + if(ret == 1)break; + retries++; + } + + if (retries >= IIC_RETRY_NUM) + { + icn83xx_error("%s i2c read error: %d\n", __func__, ret); + // icn83xx_ts_reset(); + } + +#else + unsigned char tmp_buf[1]; + struct i2c_msg msgs[] = { + { + .addr = this_client->addr, + .flags = 0, + .len = 1, + .buf = tmp_buf, +#if SUPPORT_ROCKCHIP + .scl_rate = ICN83XX_I2C_SCL, +#endif + }, + { + .addr = this_client->addr, + .flags = I2C_M_RD, + .len = length, + .buf = rxdata, +#if SUPPORT_ROCKCHIP + .scl_rate = ICN83XX_I2C_SCL, +#endif + }, + }; + tmp_buf[0] = addr; + + while(retries < IIC_RETRY_NUM) + { + ret = i2c_transfer(this_client->adapter, msgs, 2); + if(ret == 2)break; + retries++; + } + + if (retries >= IIC_RETRY_NUM) + { + icn83xx_error("%s i2c read error: %d\n", __func__, ret); + icn83xx_ts_reset(); + } +#endif + + return ret; +} +/*********************************************************************************************** +Name : icn83xx_i2c_txdata +Input : addr + *rxdata + length +Output : ret +function : send data to icn83xx , normal mode + ***********************************************************************************************/ +int icn83xx_i2c_txdata(unsigned char addr, char *txdata, int length) +{ + int ret = -1; + unsigned char tmp_buf[128]; + int retries = 0; + + struct i2c_msg msg[] = { + { + .addr = this_client->addr, + .flags = 0, + .len = length + 1, + .buf = tmp_buf, +#if SUPPORT_ROCKCHIP + .scl_rate = ICN83XX_I2C_SCL, +#endif + }, + }; + + if (length > 125) + { + icn83xx_error("%s too big datalen = %d!\n", __func__, length); + return -1; + } + + tmp_buf[0] = addr; + + if (length != 0 && txdata != NULL) + { + memcpy(&tmp_buf[1], txdata, length); + } + + while(retries < IIC_RETRY_NUM) + { + ret = i2c_transfer(this_client->adapter, msg, 1); + if(ret == 1)break; + retries++; + } + + if (retries >= IIC_RETRY_NUM) + { + icn83xx_error("%s i2c write error: %d\n", __func__, ret); + icn83xx_ts_reset(); + } + + return ret; +} + +/*********************************************************************************************** +Name : icn83xx_write_reg +Input : addr -- address +para -- parameter +Output : +function : write register of icn83xx, normal mode + ***********************************************************************************************/ +int icn83xx_write_reg(unsigned char addr, char para) +{ + char buf[3]; + int ret = -1; + + buf[0] = para; + ret = icn83xx_i2c_txdata(addr, buf, 1); + if (ret < 0) { + icn83xx_error("write reg failed! %#x ret: %d\n", buf[0], ret); + return -1; + } + + return ret; +} + + +/*********************************************************************************************** +Name : icn83xx_read_reg +Input : addr +pdata +Output : +function : read register of icn83xx, normal mode + ***********************************************************************************************/ +int icn83xx_read_reg(unsigned char addr, char *pdata) +{ + int ret = -1; + ret = icn83xx_i2c_rxdata(addr, pdata, 1); + return ret; +} + +#if SUPPORT_FW_UPDATE +/*********************************************************************************************** +Name : icn83xx_log +Input : 0: rawdata, 1: diff data +Output : err type +function : calibrate param + ***********************************************************************************************/ +void icn83xx_log(char diff) +{ + char row = 0; + char column = 0; + int i, j; + icn83xx_read_reg(160, &row); + icn83xx_read_reg(161, &column); + + if(diff == 1) + { + icn83xx_readTP(row, column, (char *)&log_diffdata[0][0]); + + for(i=0; i<row; i++) + { + for(j=0; j<column; j++) + { + log_diffdata[i][j] = log_diffdata[i][j] - log_rawdata[i][j]; + } + } + icn83xx_rawdatadump(&log_diffdata[0][0], row*16, 16); + } + else + { + icn83xx_readTP(row, column, (char *)&log_rawdata[0][0]); + icn83xx_rawdatadump(&log_rawdata[0][0], row*16, 16); + } +} +#endif + +/*********************************************************************************************** +Name : icn83xx_iic_test +Input : void +Output : +function : 0 success, + ***********************************************************************************************/ +static int icn83xx_iic_test(void) +{ + int ret = -1; + char value = 0; + int retry = 0; + while(retry++ < 3) + { + ret = icn83xx_read_reg(0, &value); + if(ret > 0) + { + return ret; + } + icn83xx_error("iic test error! %d\n", retry); + msleep(3); + } + return ret; +} + +/*********************************************************************************************** +Name : icn83xx_report_value_B +Input : void +Output : +function : reprot touch ponit + ***********************************************************************************************/ +#if CTP_REPORT_PROTOCOL +static int icn83xx_report_value_B(void) +{ + struct icn83xx_ts_data *icn83xx_ts = i2c_get_clientdata(this_client); + char buf[POINT_NUM*POINT_SIZE+3]={0}; + static unsigned char finger_last[POINT_NUM + 1]={0}; + unsigned char finger_current[POINT_NUM + 1] = {0}; + unsigned int position = 0; + int temp = 0; + int ret = -1; + int x,y; + icn83xx_info("==icn83xx_report_value_B ==\n"); + // icn83xx_trace("==icn83xx_report_value_B ==\n"); + ret = icn83xx_i2c_rxdata(16, buf, POINT_NUM*POINT_SIZE+2); + if (ret < 0) { + icn83xx_error("%s read_data i2c_rxdata failed: %d\n", __func__, ret); + return ret; + } + + icn83xx_ts->point_num = buf[1]; + if (icn83xx_ts->point_num > 5) { + printk("error point_num : %d\n",icn83xx_ts->point_num); + return -1; + } + if(icn83xx_ts->point_num > 0) + { + for(position = 0; position<icn83xx_ts->point_num; position++) + { + temp = buf[2 + POINT_SIZE*position] + 1; + finger_current[temp] = 1; + icn83xx_ts->point_info[temp].u8ID = buf[2 + POINT_SIZE*position]; + icn83xx_ts->point_info[temp].u16PosX = (buf[3 + POINT_SIZE*position]<<8) + buf[4 + POINT_SIZE*position]; + icn83xx_ts->point_info[temp].u16PosY = (buf[5 + POINT_SIZE*position]<<8) + buf[6 + POINT_SIZE*position]; + icn83xx_ts->point_info[temp].u8Pressure = buf[7 + POINT_SIZE*position]; + icn83xx_ts->point_info[temp].u8EventId = buf[8 + POINT_SIZE*position]; + + if(icn83xx_ts->point_info[temp].u8EventId == 4) + finger_current[temp] = 0; + + if(1 == icn83xx_ts->revert_x_flag) + { + icn83xx_ts->point_info[temp].u16PosX = icn83xx_ts->screen_max_x- icn83xx_ts->point_info[temp].u16PosX; + } + if(1 == icn83xx_ts->revert_y_flag) + { + icn83xx_ts->point_info[temp].u16PosY = icn83xx_ts->screen_max_y- icn83xx_ts->point_info[temp].u16PosY; + } + icn83xx_info("temp %d\n", temp); + icn83xx_info("u8ID %d\n", icn83xx_ts->point_info[temp].u8ID); + icn83xx_info("u16PosX %d\n", icn83xx_ts->point_info[temp].u16PosX); + icn83xx_info("u16PosY %d\n", icn83xx_ts->point_info[temp].u16PosY); + icn83xx_info("u8Pressure %d\n", icn83xx_ts->point_info[temp].u8Pressure); + icn83xx_info("u8EventId %d\n", icn83xx_ts->point_info[temp].u8EventId); + //icn83xx_info("u8Pressure %d\n", icn83xx_ts->point_info[temp].u8Pressure*16); + } + } + else + { + for(position = 1; position < POINT_NUM+1; position++) + { + finger_current[position] = 0; + } + icn83xx_info("no touch\n"); + } + + for(position = 1; position < POINT_NUM + 1; position++) + { + if((finger_current[position] == 0) && (finger_last[position] != 0)) + { + input_mt_slot(icn83xx_ts->input_dev, position-1); + input_mt_report_slot_state(icn83xx_ts->input_dev, MT_TOOL_FINGER, false); + icn83xx_point_info("one touch up: %d\n", position); + } + else if(finger_current[position]) + { + if (g_param.xyswap == 0) + { + x = icn83xx_ts->point_info[position].u16PosX; + y = icn83xx_ts->point_info[position].u16PosY; + } else { + y = icn83xx_ts->point_info[position].u16PosX; + x = icn83xx_ts->point_info[position].u16PosY; + } + if (g_param.xdir == -1) + { + x = g_param.panelres_x - x; + } + if (g_param.ydir == -1) + { + y = g_param.panelres_y - y; + } + + if (g_param.lcd_exchg) { + int tmp; + tmp = x; + x = y; + y = g_param.panelres_x - tmp; + } + + input_mt_slot(icn83xx_ts->input_dev, position-1); + input_mt_report_slot_state(icn83xx_ts->input_dev, MT_TOOL_FINGER, true); + input_report_abs(icn83xx_ts->input_dev, ABS_MT_TOUCH_MAJOR, 1); + //input_report_abs(icn83xx_ts->input_dev, ABS_MT_PRESSURE, icn83xx_ts->point_info[position].u8Pressure); + input_report_abs(icn83xx_ts->input_dev, ABS_MT_PRESSURE, 200); + input_report_abs(icn83xx_ts->input_dev, ABS_MT_POSITION_X, x); + input_report_abs(icn83xx_ts->input_dev, ABS_MT_POSITION_Y, y); + icn83xx_point_info("===position: %d, x = %d,y = %d, press = %d ====\n", position, icn83xx_ts->point_info[position].u16PosX,icn83xx_ts->point_info[position].u16PosY, icn83xx_ts->point_info[position].u8Pressure); + // icn83xx_trace("===position: %d, x = %d,y = %d, press = %d ====\n", position, icn83xx_ts->point_info[position].u16PosX,icn83xx_ts->point_info[position].u16PosY, icn83xx_ts->point_info[position].u8Pressure); + dbg("raw%d(%d,%d), rpt%d(%d,%d)\n", position, icn83xx_ts->point_info[position].u16PosX, icn83xx_ts->point_info[position].u16PosY, position, x, y); + } + + } + input_sync(icn83xx_ts->input_dev); + + for(position = 1; position < POINT_NUM + 1; position++) + { + finger_last[position] = finger_current[position]; + } + return 0; +} + +#else + +/*********************************************************************************************** +Name : icn83xx_ts_release +Input : void +Output : +function : touch release + ***********************************************************************************************/ +static void icn83xx_ts_release(void) +{ + struct icn83xx_ts_data *icn83xx_ts = i2c_get_clientdata(this_client); + icn83xx_info("==icn83xx_ts_release ==\n"); + input_report_abs(icn83xx_ts->input_dev, ABS_MT_TOUCH_MAJOR, 0); + input_sync(icn83xx_ts->input_dev); +} + +/*********************************************************************************************** +Name : icn83xx_report_value_A +Input : void +Output : +function : reprot touch ponit + ***********************************************************************************************/ +static int icn83xx_report_value_A(void) +{ + struct icn83xx_ts_data *icn83xx_ts = i2c_get_clientdata(this_client); + char buf[POINT_NUM*POINT_SIZE+3]={0}; + int ret = -1; + int i; +#if TOUCH_VIRTUAL_KEYS + unsigned char button; + static unsigned char button_last; +#endif + icn83xx_info("==icn83xx_report_value_A ==\n"); + + ret = icn83xx_i2c_rxdata(16, buf, POINT_NUM*POINT_SIZE+2); + if (ret < 0) { + icn83xx_error("%s read_data i2c_rxdata failed: %d\n", __func__, ret); + return ret; + } +#if TOUCH_VIRTUAL_KEYS + button = buf[0]; + icn83xx_info("%s: button=%d\n",__func__, button); + + if((button_last != 0) && (button == 0)) + { + icn83xx_ts_release(); + button_last = button; + return 1; + } + if(button != 0) + { + switch(button) + { + case ICN_VIRTUAL_BUTTON_HOME: + icn83xx_info("ICN_VIRTUAL_BUTTON_HOME down\n"); + input_report_abs(icn83xx_ts->input_dev, ABS_MT_TOUCH_MAJOR, 200); + input_report_abs(icn83xx_ts->input_dev, ABS_MT_POSITION_X, 280); + input_report_abs(icn83xx_ts->input_dev, ABS_MT_POSITION_Y, 1030); + input_report_abs(icn83xx_ts->input_dev, ABS_MT_WIDTH_MAJOR, 1); + input_mt_sync(icn83xx_ts->input_dev); + input_sync(icn83xx_ts->input_dev); + break; + case ICN_VIRTUAL_BUTTON_BACK: + icn83xx_info("ICN_VIRTUAL_BUTTON_BACK down\n"); + input_report_abs(icn83xx_ts->input_dev, ABS_MT_TOUCH_MAJOR, 200); + input_report_abs(icn83xx_ts->input_dev, ABS_MT_POSITION_X, 470); + input_report_abs(icn83xx_ts->input_dev, ABS_MT_POSITION_Y, 1030); + input_report_abs(icn83xx_ts->input_dev, ABS_MT_WIDTH_MAJOR, 1); + input_mt_sync(icn83xx_ts->input_dev); + input_sync(icn83xx_ts->input_dev); + break; + case ICN_VIRTUAL_BUTTON_MENU: + icn83xx_info("ICN_VIRTUAL_BUTTON_MENU down\n"); + input_report_abs(icn83xx_ts->input_dev, ABS_MT_TOUCH_MAJOR, 200); + input_report_abs(icn83xx_ts->input_dev, ABS_MT_POSITION_X, 100); + input_report_abs(icn83xx_ts->input_dev, ABS_MT_POSITION_Y, 1030); + input_report_abs(icn83xx_ts->input_dev, ABS_MT_WIDTH_MAJOR, 1); + input_mt_sync(icn83xx_ts->input_dev); + input_sync(icn83xx_ts->input_dev); + break; + default: + icn83xx_info("other gesture\n"); + break; + } + button_last = button; + return 1; + } +#endif + + icn83xx_ts->point_num = buf[1]; + if (icn83xx_ts->point_num == 0) { + icn83xx_ts_release(); + return 1; + } + for(i=0;i<icn83xx_ts->point_num;i++){ + if(buf[8 + POINT_SIZE*i] != 4) break ; + } + + if(i == icn83xx_ts->point_num) { + icn83xx_ts_release(); + return 1; + } + + for(i=0; i<icn83xx_ts->point_num; i++) + { + icn83xx_ts->point_info[i].u8ID = buf[2 + POINT_SIZE*i]; + icn83xx_ts->point_info[i].u16PosX = (buf[3 + POINT_SIZE*i]<<8) + buf[4 + POINT_SIZE*i]; + icn83xx_ts->point_info[i].u16PosY = (buf[5 + POINT_SIZE*i]<<8) + buf[6 + POINT_SIZE*i]; + icn83xx_ts->point_info[i].u8Pressure = 200;//buf[7 + POINT_SIZE*i]; + icn83xx_ts->point_info[i].u8EventId = buf[8 + POINT_SIZE*i]; + + if(1 == icn83xx_ts->revert_x_flag) + { + icn83xx_ts->point_info[i].u16PosX = icn83xx_ts->screen_max_x- icn83xx_ts->point_info[i].u16PosX; + } + if(1 == icn83xx_ts->revert_y_flag) + { + icn83xx_ts->point_info[i].u16PosY = icn83xx_ts->screen_max_y- icn83xx_ts->point_info[i].u16PosY; + } + + icn83xx_info("u8ID %d\n", icn83xx_ts->point_info[i].u8ID); + icn83xx_info("u16PosX %d\n", icn83xx_ts->point_info[i].u16PosX); + icn83xx_info("u16PosY %d\n", icn83xx_ts->point_info[i].u16PosY); + icn83xx_info("u8Pressure %d\n", icn83xx_ts->point_info[i].u8Pressure); + icn83xx_info("u8EventId %d\n", icn83xx_ts->point_info[i].u8EventId); + + + input_report_abs(icn83xx_ts->input_dev, ABS_MT_TRACKING_ID, icn83xx_ts->point_info[i].u8ID); + input_report_abs(icn83xx_ts->input_dev, ABS_MT_TOUCH_MAJOR, icn83xx_ts->point_info[i].u8Pressure); + input_report_abs(icn83xx_ts->input_dev, ABS_MT_POSITION_X, icn83xx_ts->point_info[i].u16PosX); + input_report_abs(icn83xx_ts->input_dev, ABS_MT_POSITION_Y, icn83xx_ts->point_info[i].u16PosY); + input_report_abs(icn83xx_ts->input_dev, ABS_MT_WIDTH_MAJOR, 1); + input_mt_sync(icn83xx_ts->input_dev); + icn83xx_point_info("point: %d ===x = %d,y = %d, press = %d ====\n",i, icn83xx_ts->point_info[i].u16PosX,icn83xx_ts->point_info[i].u16PosY, icn83xx_ts->point_info[i].u8Pressure); + } + + input_sync(icn83xx_ts->input_dev); + return 0; +} +#endif + +/*********************************************************************************************** +Name : icn83xx_ts_pen_irq_work +Input : void +Output : +function : work_struct + ***********************************************************************************************/ +static void icn83xx_ts_pen_irq_work(struct work_struct *work) +{ + struct icn83xx_ts_data *icn83xx_ts = i2c_get_clientdata(this_client); +#if SUPPORT_PROC_FS + if(down_interruptible(&icn83xx_ts->sem)) + { + return; + } +#endif + + if(icn83xx_ts->work_mode == 0) + { +#if CTP_REPORT_PROTOCOL + icn83xx_report_value_B(); +#else + icn83xx_report_value_A(); +#endif + + } +#if SUPPORT_FW_UPDATE + else if(icn83xx_ts->work_mode == 1) + { + printk("log raw data\n"); + icn83xx_log(0); //raw data + } + else if(icn83xx_ts->work_mode == 2) + { + printk("log diff data\n"); + icn83xx_log(1); //diff data + } +#endif + +#if SUPPORT_PROC_FS + up(&icn83xx_ts->sem); +#endif + wmt_gpio_unmask_irq(g_param.irqgpio); + +} +/*********************************************************************************************** +Name : chipone_timer_func +Input : void +Output : +function : Timer interrupt service routine. + ***********************************************************************************************/ +static enum hrtimer_restart chipone_timer_func(struct hrtimer *timer) +{ + struct icn83xx_ts_data *icn83xx_ts = container_of(timer, struct icn83xx_ts_data, timer); + queue_work(icn83xx_ts->ts_workqueue, &icn83xx_ts->pen_event_work); + + if(icn83xx_ts->use_irq == 1) + { + if((icn83xx_ts->work_mode == 1) || (icn83xx_ts->work_mode == 2)) + { + hrtimer_start(&icn83xx_ts->timer, ktime_set(CTP_POLL_TIMER/1000, (CTP_POLL_TIMER%1000)*1000000), HRTIMER_MODE_REL); + } + } + else + { + hrtimer_start(&icn83xx_ts->timer, ktime_set(CTP_POLL_TIMER/1000, (CTP_POLL_TIMER%1000)*1000000), HRTIMER_MODE_REL); + } + return HRTIMER_NORESTART; +} +/*********************************************************************************************** +Name : icn83xx_ts_interrupt +Input : void +Output : +function : interrupt service routine + ***********************************************************************************************/ +static irqreturn_t icn83xx_ts_interrupt(int irq, void *dev_id) +{ + struct icn83xx_ts_data *icn83xx_ts = dev_id; + int irqindex = g_param.irqgpio; + + icn83xx_info("==========------icn83xx_ts TS Interrupt-----============\n"); + if (gpio_irqstatus(irqindex)) { + wmt_gpio_ack_irq(irqindex); + if (is_gpio_irqenable(irqindex) && l_suspend == 0) { + wmt_gpio_mask_irq(irqindex); + if(icn83xx_ts->work_mode != 0) { + wmt_gpio_unmask_irq(irqindex); + return IRQ_HANDLED; + } + //icn83xx_irq_disable(); + if (!work_pending(&icn83xx_ts->pen_event_work)) { + //icn83xx_info("Enter work\n"); + queue_work(icn83xx_ts->ts_workqueue, &icn83xx_ts->pen_event_work); + } + } + return IRQ_HANDLED; + } + return IRQ_NONE; +} + + +#ifdef CONFIG_HAS_EARLYSUSPEND +/*********************************************************************************************** +Name : icn83xx_ts_suspend +Input : void +Output : +function : tp enter sleep mode + ***********************************************************************************************/ +static void icn83xx_ts_early_suspend(struct early_suspend *handler) +{ + int retry = 0; + struct icn83xx_ts_data *icn83xx_ts = i2c_get_clientdata(this_client); + icn83xx_trace("icn83xx_ts_suspend: write ICN83XX_REG_PMODE .\n"); + if (icn83xx_ts->use_irq) + { + icn83xx_irq_disable(); + icn83xx_trace("icn83xx_ts_suspend:disable irq .\n"); + } + else + { + hrtimer_cancel(&icn83xx_ts->timer); + } + for(retry = 0;retry <3; retry++ ) + { + icn83xx_write_reg(ICN83XX_REG_PMODE, PMODE_HIBERNATE); + } +} + +/*********************************************************************************************** +Name : icn83xx_ts_resume +Input : void +Output : +function : wakeup tp or reset tp + ***********************************************************************************************/ +static void icn83xx_ts_late_resume(struct early_suspend *handler) +{ + struct icn83xx_ts_data *icn83xx_ts = i2c_get_clientdata(this_client); + int i; + printk("==icn83xx_ts_resume== \n"); + // icn83xx_ts_reset(); + //report touch release +#if CTP_REPORT_PROTOCOL + for(i = 0; i < POINT_NUM; i++) + { + input_mt_slot(icn83xx_ts->input_dev, i); + input_mt_report_slot_state(icn83xx_ts->input_dev, MT_TOOL_FINGER, false); + } +#else + icn83xx_ts_release(); +#endif + icn83xx_ts_wakeup(); + icn83xx_ts_reset(); + if (icn83xx_ts->use_irq) + { + printk("icn83xx_irq_enable\n"); + icn83xx_irq_enable(); + } + else + { printk("icn83xx_ts_resume hrtimer_start\n"); + hrtimer_start(&icn83xx_ts->timer, ktime_set(CTP_START_TIMER/1000, (CTP_START_TIMER%1000)*1000000), HRTIMER_MODE_REL); + } + +} +#endif + +#ifdef CONFIG_PM +/*********************************************************************************************** +Name : icn83xx_ts_suspend +Input : void +Output : +function : tp enter sleep mode + ***********************************************************************************************/ +static int icn83xx_ts_suspend(struct device *pdev) +{ + //int retry = 0; + struct icn83xx_ts_data *icn83xx_ts = i2c_get_clientdata(this_client); + icn83xx_trace("icn83xx_ts_suspend: write ICN83XX_REG_PMODE .\n"); + if (icn83xx_ts->use_irq) + { + icn83xx_irq_disable(); + icn83xx_trace("icn83xx_ts_suspend:disable irq .\n"); + } + else + { + hrtimer_cancel(&icn83xx_ts->timer); + } + /*for(retry = 0;retry <3; retry++ ) + { + icn83xx_write_reg(ICN83XX_REG_PMODE, PMODE_HIBERNATE); + } */ + l_suspend = 1; + return 0; +} + +/*********************************************************************************************** +Name : icn83xx_ts_resume +Input : void +Output : +function : wakeup tp or reset tp + ***********************************************************************************************/ +static int icn83xx_ts_resume(struct device *pdev) +{ + struct icn83xx_ts_data *icn83xx_ts = i2c_get_clientdata(this_client); + int i; + printk("==icn83xx_ts_resume== \n"); + // icn83xx_ts_reset(); + //report touch release +#if CTP_REPORT_PROTOCOL + for(i = 0; i < POINT_NUM; i++) + { + input_mt_slot(icn83xx_ts->input_dev, i); + input_mt_report_slot_state(icn83xx_ts->input_dev, MT_TOOL_FINGER, false); + } +#else + icn83xx_ts_release(); +#endif + //icn83xx_ts_wakeup(); + icn83xx_ts_reset(); + l_suspend = 0; + if (icn83xx_ts->use_irq) + { + printk("icn83xx_irq_enable\n"); + icn83xx_irq_enable(); + } + else + { printk("icn83xx_ts_resume hrtimer_start\n"); + hrtimer_start(&icn83xx_ts->timer, ktime_set(CTP_START_TIMER/1000, (CTP_START_TIMER%1000)*1000000), HRTIMER_MODE_REL); + } + return 0; +} +#else +#define icn83xx_ts_suspend NULL +#define icn83xx_ts_resume NULL +#endif + +/*********************************************************************************************** +Name : icn83xx_request_io_port +Input : void +Output : +function : 0 success, + ***********************************************************************************************/ +static int icn83xx_request_io_port(struct icn83xx_ts_data *icn83xx_ts) +{ +#if SUPPORT_ROCKCHIP + icn83xx_ts->screen_max_x = SCREEN_MAX_X; + icn83xx_ts->screen_max_y = SCREEN_MAX_Y; + icn83xx_ts->irq = CTP_IRQ_PORT; +#endif + icn83xx_ts->irq = IRQ_GPIO; + + if (gpio_request(g_param.rstgpio, "ts_rst") < 0) { + printk("gpio(%d) touchscreen reset request fail\n", g_param.rstgpio); + return -EIO; + } + gpio_direction_output(g_param.rstgpio, 1); + + if (gpio_request(g_param.irqgpio, "ts_irq") < 0) { + printk("gpio(%d) touchscreen interrupt request fail\n", g_param.irqgpio); + gpio_free(g_param.rstgpio); + return -EIO; + } + wmt_gpio_setpull(g_param.irqgpio, WMT_GPIO_PULL_UP); + gpio_direction_input(g_param.irqgpio); + + return 0; +} + +/*********************************************************************************************** +Name : icn83xx_free_io_port +Input : void +Output : +function : 0 success, + ***********************************************************************************************/ +static void icn83xx_free_io_port(void) +{ + gpio_free(g_param.rstgpio); + gpio_free(g_param.irqgpio); +} + +/*********************************************************************************************** +Name : icn83xx_request_irq +Input : void +Output : +function : 0 success, + ***********************************************************************************************/ +static int icn83xx_request_irq(struct icn83xx_ts_data *icn83xx_ts) +{ + int err = -1; + + /*err = gpio_request(icn83xx_ts->irq, "TS_INT"); //Request IO + if (err < 0) + { + icn83xx_error("Failed to request GPIO:%d, ERRNO:%d\n", (int)icn83xx_ts->irq, err); + return err; + } + gpio_direction_input(icn83xx_ts->irq);*/ + + wmt_gpio_set_irq_type(g_param.irqgpio, IRQ_TYPE_EDGE_FALLING); + err = request_irq(icn83xx_ts->irq, icn83xx_ts_interrupt, IRQF_SHARED, "icn83xx_ts", icn83xx_ts); + if (err < 0) + { + icn83xx_error("icn83xx_ts_probe: request irq failed\n"); + return err; + } + else + { + icn83xx_irq_disable(); + icn83xx_ts->use_irq = 1; + } + + return 0; +} + + +/*********************************************************************************************** +Name : icn83xx_free_irq +Input : void +Output : +function : 0 success, + ***********************************************************************************************/ +static void icn83xx_free_irq(struct icn83xx_ts_data *icn83xx_ts) +{ + if (icn83xx_ts) + { + if (icn83xx_ts->use_irq) + { + free_irq(icn83xx_ts->irq, icn83xx_ts); + } + else + { + hrtimer_cancel(&icn83xx_ts->timer); + } + } +} + +/*********************************************************************************************** +Name : icn83xx_request_input_dev +Input : void +Output : +function : 0 success, + ***********************************************************************************************/ +static int icn83xx_request_input_dev(struct icn83xx_ts_data *icn83xx_ts) +{ + int ret = -1; + struct input_dev *input_dev; + + input_dev = input_allocate_device(); + if (!input_dev) { + icn83xx_error("failed to allocate input device\n"); + return -ENOMEM; + } + icn83xx_ts->input_dev = input_dev; + + icn83xx_ts->input_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) ; +#if CTP_REPORT_PROTOCOL + __set_bit(INPUT_PROP_DIRECT, icn83xx_ts->input_dev->propbit); + input_mt_init_slots(icn83xx_ts->input_dev, 255); +#else + set_bit(ABS_MT_TOUCH_MAJOR, icn83xx_ts->input_dev->absbit); + set_bit(ABS_MT_POSITION_X, icn83xx_ts->input_dev->absbit); + set_bit(ABS_MT_POSITION_Y, icn83xx_ts->input_dev->absbit); + set_bit(ABS_MT_WIDTH_MAJOR, icn83xx_ts->input_dev->absbit); +#endif + if (g_param.lcd_exchg) { + input_set_abs_params(icn83xx_ts->input_dev, ABS_MT_POSITION_X, 0, g_param.panelres_y, 0, 0); + input_set_abs_params(icn83xx_ts->input_dev, ABS_MT_POSITION_Y, 0, g_param.panelres_x, 0, 0); + } else { + input_set_abs_params(icn83xx_ts->input_dev, ABS_MT_POSITION_X, 0, g_param.panelres_x, 0, 0); + input_set_abs_params(icn83xx_ts->input_dev, ABS_MT_POSITION_Y, 0, g_param.panelres_y, 0, 0); + } + input_set_abs_params(icn83xx_ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0); + input_set_abs_params(icn83xx_ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); + input_set_abs_params(icn83xx_ts->input_dev, ABS_MT_TRACKING_ID, 0, 255, 0, 0); + + __set_bit(KEY_MENU, input_dev->keybit); + __set_bit(KEY_BACK, input_dev->keybit); + __set_bit(KEY_HOME, input_dev->keybit); + __set_bit(KEY_SEARCH, input_dev->keybit); + + input_dev->name = CTP_NAME; + ret = input_register_device(input_dev); + if (ret) { + icn83xx_error("Register %s input device failed\n", input_dev->name); + input_free_device(input_dev); + return -ENODEV; + } + +#ifdef CONFIG_HAS_EARLYSUSPEND + icn83xx_trace("==register_early_suspend =\n"); + icn83xx_ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1; + icn83xx_ts->early_suspend.suspend = icn83xx_ts_early_suspend; + icn83xx_ts->early_suspend.resume = icn83xx_ts_late_resume; + register_early_suspend(&icn83xx_ts->early_suspend); +#endif + + return 0; +} + +#if SUPPORT_DELAYED_WORK +static void icn_delayedwork_fun(struct work_struct *work) +{ + int retry; + short fwVersion = 0; + short curVersion = 0; + icn83xx_trace("====%s begin1111=====. \n", __func__); + +#if SUPPORT_FW_UPDATE + fwVersion = icn83xx_read_fw_Ver(firmware); + curVersion = icn83xx_readVersion(); + icn83xx_trace("fwVersion : 0x%x\n", fwVersion); + icn83xx_trace("current version: 0x%x\n", curVersion); + + +#if FORCE_UPDATA_FW + retry = 5; + while(retry > 0) + { + if(R_OK == icn83xx_fw_update(firmware)) + { + break; + } + retry--; + icn83xx_error("icn83xx_fw_update failed.\n"); + } +#else + if(fwVersion > curVersion) + { + retry = 5; + while(retry > 0) + { + if(R_OK == icn83xx_fw_update(firmware)) + { + break; + } + retry--; + icn83xx_error("icn83xx_fw_update failed.\n"); + } + } +#endif + +#endif + + + icn83xx_irq_enable(); + icn83xx_trace("====%s over1111=====. \n", __func__); +} +#endif + + +char FbCap[4][16]={ + {0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14}, + {0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12}, + {0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, + {0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08}, +}; + +static int wmt_wakeup_bl_notify(struct notifier_block *nb, unsigned long event, + void *dummy) +{ + //printk("get notify\n"); + switch (event) { + case BL_CLOSE: + l_suspend = 1; + //printk("\nclose backlight\n\n"); + //printk("disable irq\n\n"); + wmt_gpio_mask_irq(g_param.irqgpio); + break; + case BL_OPEN: + l_suspend = 0; + //printk("\nopen backlight\n\n"); + //printk("enable irq\n\n"); + wmt_gpio_unmask_irq(g_param.irqgpio); + break; + } + + return NOTIFY_OK; +} + +static struct notifier_block wmt_bl_notify = { + .notifier_call = wmt_wakeup_bl_notify, +}; + +static int icn83xx_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct icn83xx_ts_data *icn83xx_ts; + short fwVersion = 0; + short curVersion = 0; + //int average; + int err = 0; + //char value; + int retry; + + icn83xx_trace("====%s begin=====. \n", __func__); + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) + { + icn83xx_error("I2C check functionality failed.\n"); + return -ENODEV; + } + + icn83xx_ts = kzalloc(sizeof(*icn83xx_ts), GFP_KERNEL); + if (!icn83xx_ts) + { + icn83xx_error("Alloc icn83xx_ts memory failed.\n"); + return -ENOMEM; + } + + this_client = client; + i2c_set_clientdata(client, icn83xx_ts); + + icn83xx_ts->work_mode = 0; + spin_lock_init(&icn83xx_ts->irq_lock); + // icn83xx_ts->irq_lock = SPIN_LOCK_UNLOCKED; + + err = icn83xx_request_io_port(icn83xx_ts); + if (err != 0) { + icn83xx_error("icn83xx_request_io_port failed.\n"); + goto fail1; + } + + memset(firmware, 0, 128); + sprintf(firmware,"/system/etc/firmware/%s.bin",g_param.fw_name); + + icn83xx_ts_reset(); + err = icn83xx_iic_test(); + if (err < 0) + { + icn83xx_error("icn83xx_iic_test failed.\n"); +#if SUPPORT_FW_UPDATE + +#if COMPILE_FW_WITH_DRIVER + icn83xx_set_fw(sizeof(icn83xx_fw), &icn83xx_fw[0]); +#endif + if(icn83xx_check_progmod() == 0) + { + + retry = 5; + icn83xx_trace("in prog mode\n"); + while(retry > 0) + { + if(R_OK == icn83xx_fw_update(firmware)) + { + break; + } + retry--; + icn83xx_error("icn83xx_fw_update failed.\n"); + } + } + else // + { + icn83xx_error("I2C communication failed.\n"); + err = -1; + goto fail2; + } + +#endif + } + else + { + icn83xx_trace("iic communication ok\n"); + } + +#if SUPPORT_FW_UPDATE + fwVersion = icn83xx_read_fw_Ver(firmware); + curVersion = icn83xx_readVersion(); + icn83xx_trace("fwVersion : 0x%x\n", fwVersion); + icn83xx_trace("current version: 0x%x\n", curVersion); + + if (g_param.force_download) { + retry = 5; + while(retry > 0) + { + if(R_OK == icn83xx_fw_update(firmware)) + { + break; + } + retry--; + icn83xx_error("icn83xx_fw_update failed.\n"); + } + } else { + if(fwVersion > curVersion) + { + retry = 5; + while(retry > 0) + { + if(R_OK == icn83xx_fw_update(firmware)) + { + break; + } + retry--; + icn83xx_error("icn83xx_fw_update failed.\n"); + } + } + } + +#endif + +#if SUPPORT_FW_CALIB + err = icn83xx_read_reg(0, &value); + if(err > 0) + { + //auto calib fw + average = icn83xx_calib(0, NULL); + //fix FbCap + // average = icn83xx_calib(0, FbCap[1]); + icn83xx_trace("average : %d\n", average); + icn83xx_setPeakGroup(250, 150); + icn83xx_setDownUp(400, 300); + } +#endif + + INIT_WORK(&icn83xx_ts->pen_event_work, icn83xx_ts_pen_irq_work); + icn83xx_ts->ts_workqueue = create_singlethread_workqueue(dev_name(&client->dev)); + if (!icn83xx_ts->ts_workqueue) { + icn83xx_error("create_singlethread_workqueue failed.\n"); + err = -ESRCH; + goto fail3; + } + + err= icn83xx_request_input_dev(icn83xx_ts); + if (err < 0) + { + icn83xx_error("request input dev failed\n"); + goto fail4; + } + +#if TOUCH_VIRTUAL_KEYS + icn83xx_ts_virtual_keys_init(); +#endif + err = icn83xx_request_irq(icn83xx_ts); + if (err != 0) + { + printk("request irq error, use timer\n"); + icn83xx_ts->use_irq = 0; + hrtimer_init(&icn83xx_ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + icn83xx_ts->timer.function = chipone_timer_func; + hrtimer_start(&icn83xx_ts->timer, ktime_set(CTP_START_TIMER/1000, (CTP_START_TIMER%1000)*1000000), HRTIMER_MODE_REL); + } +#if SUPPORT_SYSFS + icn83xx_create_sysfs(client); +#endif + +#if SUPPORT_PROC_FS + sema_init(&icn83xx_ts->sem, 1); + init_proc_node(); +#endif + + err = device_create_file(&(client->dev), &dev_attr_dbg); + if (err) { + printk("Can't create attr file"); + } + if (g_param.earlysus_en) + register_bl_notifier(&wmt_bl_notify); + +#if SUPPORT_DELAYED_WORK + INIT_DELAYED_WORK(&icn83xx_ts->icn_delayed_work, icn_delayedwork_fun); + schedule_delayed_work(&icn83xx_ts->icn_delayed_work, msecs_to_jiffies(8000)); +#else + + icn83xx_irq_enable(); +#endif + icn83xx_trace("==%s over =\n", __func__); + return 0; + +fail4: + input_unregister_device(icn83xx_ts->input_dev); + input_free_device(icn83xx_ts->input_dev); +fail3: + cancel_work_sync(&icn83xx_ts->pen_event_work); +fail2: + icn83xx_free_io_port(); +fail1: + kfree(icn83xx_ts); + return err; +} + +static int __devexit icn83xx_ts_remove(struct i2c_client *client) +{ + struct icn83xx_ts_data *icn83xx_ts = i2c_get_clientdata(client); + icn83xx_trace("==icn83xx_ts_remove=\n"); + icn83xx_irq_disable(); +#ifdef CONFIG_HAS_EARLYSUSPEND + unregister_early_suspend(&icn83xx_ts->early_suspend); +#endif + + if (g_param.earlysus_en) + unregister_bl_notifier(&wmt_bl_notify); + +#if SUPPORT_PROC_FS + uninit_proc_node(); +#endif + + input_unregister_device(icn83xx_ts->input_dev); + input_free_device(icn83xx_ts->input_dev); + cancel_work_sync(&icn83xx_ts->pen_event_work); + destroy_workqueue(icn83xx_ts->ts_workqueue); + icn83xx_free_irq(icn83xx_ts); + icn83xx_free_io_port(); + kfree(icn83xx_ts); + i2c_set_clientdata(client, NULL); + return 0; +} + +static int wmt_check_touch_env(void) +{ + int ret = 0; + int len = 96; + char retval[200] = {0},*p=NULL,*s=NULL; + int Enable=0; + + // Get u-boot parameter + /*ret = wmt_getsyspara("wmt.io.zettouch", retval, &len); + if(ret){ + klog("Read wmt.io.zettouch Failed.\n"); + } else + goto paste;*/ + ret = wmt_getsyspara("wmt.io.touch", retval, &len); + if(ret){ + printk("Read wmt.io.touch Failed.\n"); + return -EIO; + } + +//paste: + p = retval; + Enable = (p[0] - '0' == 1) ? 1 : 0; + if(Enable == 0){ + printk("Touch Screen Is Disabled.\n"); + return -ENODEV; + } + + p = strchr(p,':');p++; + s = strchr(p,':'); + strncpy(g_param.fw_name,p, (s-p)); + printk("ts_name=%s\n", g_param.fw_name); + if (strncmp(g_param.fw_name, "ICN83", 5)) { + printk("Wrong firmware name.\n"); + return -ENODEV; + } + + p = s+1; + ret = sscanf(p,"%d:%d:%d:%d:%d:%d:%d:%d", + &(g_param.irqgpio),&(g_param.panelres_x),&(g_param.panelres_y),&(g_param.rstgpio), + &(g_param.xyswap),&(g_param.xdir),&(g_param.ydir),&(g_param.force_download)); + + if (ret < 8) { + printk("Wrong format ts u-boot param(%d)!\nwmt.io.touch=%s\n",ret,retval); + return -ENODEV; + } + + printk("p.x = %d, p.y = %d, irqgpio=%d, rstgpio=%d,xyswap=%d,xdir=%d,ydir=%d,force_download=%d\n", + g_param.panelres_x,g_param.panelres_y,g_param.irqgpio,g_param.rstgpio, + g_param.xyswap,g_param.xdir,g_param.ydir,g_param.force_download); + + memset(retval,0,sizeof(retval)); + ret = wmt_getsyspara("wmt.touch.earlysus", retval, &len); + if(!ret) + g_param.earlysus_en = (retval[0] - '0' == 1) ? 1 : 0; + + memset(retval,0,sizeof(retval)); + ret = wmt_getsyspara("wmt.display.fb0", retval, &len); + if (!ret) { + int tmp[6]; + p = retval; + sscanf(p, "%d:[%d:%d:%d:%d:%d", &tmp[0], &tmp[1], &tmp[2], &tmp[3], &tmp[4], &tmp[5]); + if (tmp[4] > tmp[5]) + g_param.lcd_exchg = 1; + } + + return 0; +} + +static const struct dev_pm_ops icn83xx_pm_ops = { + .suspend = icn83xx_ts_suspend, + .resume = icn83xx_ts_resume, +}; + +static const struct i2c_device_id icn83xx_ts_id[] = { + { CTP_NAME, 0 }, + {}, +}; +MODULE_DEVICE_TABLE(i2c, icn83xx_ts_id); + +static struct i2c_driver icn83xx_ts_driver = { + .driver = { + .name = CTP_NAME, + .pm = &icn83xx_pm_ops, + }, + .probe = icn83xx_ts_probe, + .remove = __devexit_p(icn83xx_ts_remove), + .id_table = icn83xx_ts_id, +}; + +static struct i2c_board_info i2c_board_info = { + I2C_BOARD_INFO(CTP_NAME, ICN83XX_IIC_ADDR), +}; + +static int __init icn83xx_ts_init(void) +{ + struct i2c_client *client; + struct i2c_adapter *adap; + //u8 ts_data[8]; + + icn83xx_trace("===========================%s=====================\n", __func__); + if(wmt_check_touch_env()) + return -ENODEV; + {//register i2c device + adap = i2c_get_adapter(1); //i2c Bus 1 + if (!adap) + return -ENODEV; + client = i2c_new_device(adap, &i2c_board_info); + i2c_put_adapter(adap); + if (!client) { + printk("i2c_new_device error\n"); + return -ENODEV; + } + } + /*{ //check if IC exists + if (i2c_read_tsdata(client, ts_data, 8) <= 0) { + errlog("Can't find IC!\n"); + i2c_unregister_device(client); + return -ENODEV; + } + }*/ + return i2c_add_driver(&icn83xx_ts_driver); +} + +static void __exit icn83xx_ts_exit(void) +{ + icn83xx_trace("==icn83xx_ts_exit==\n"); + i2c_unregister_device(this_client); + return i2c_del_driver(&icn83xx_ts_driver); +} + +late_initcall(icn83xx_ts_init); +module_exit(icn83xx_ts_exit); + +MODULE_AUTHOR("<zmtian@chiponeic.com>"); +MODULE_DESCRIPTION("Chipone icn83xx TouchScreen driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/input/touchscreen/icn83xx_ts/icn83xx.h b/drivers/input/touchscreen/icn83xx_ts/icn83xx.h new file mode 100755 index 00000000..46a7cf21 --- /dev/null +++ b/drivers/input/touchscreen/icn83xx_ts/icn83xx.h @@ -0,0 +1,434 @@ +/*++ + + Copyright (c) 2012-2022 ChipOne Technology (Beijing) Co., Ltd. All Rights Reserved. + This PROPRIETARY SOFTWARE is the property of ChipOne Technology (Beijing) Co., Ltd. + and may contains trade secrets and/or other confidential information of ChipOne + Technology (Beijing) Co., Ltd. This file shall not be disclosed to any third party, + in whole or in part, without prior written consent of ChipOne. + THIS PROPRIETARY SOFTWARE & ANY RELATED DOCUMENTATION ARE PROVIDED AS IS, + WITH ALL FAULTS, & WITHOUT WARRANTY OF ANY KIND. CHIPONE DISCLAIMS ALL EXPRESS OR + IMPLIED WARRANTIES. + + File Name: icn83xx.h + Abstract: + input driver. +Author: Zhimin Tian +Date : 01,17,2013 +Version: 1.0 +History : + 2012,10,30, V0.1 first version + + --*/ + +#ifndef __LINUX_ICN83XX_H__ +#define __LINUX_ICN83XX_H__ + +#include <linux/i2c.h> +#include <linux/input.h> +#ifdef CONFIG_HAS_EARLYSUSPEND + #include <linux/pm.h> + #include <linux/earlysuspend.h> +#endif +#include <linux/interrupt.h> +#include <linux/delay.h> +#include <linux/interrupt.h> +#include <linux/errno.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/platform_device.h> +#include <linux/async.h> +#include <linux/hrtimer.h> +#include <linux/init.h> +#include <linux/ioport.h> +#include <asm/irq.h> +#include <asm/io.h> +#include <asm/uaccess.h> +#include <linux/input.h> +#include <linux/input/mt.h> +#include <linux/hrtimer.h> +#include <linux/proc_fs.h> + +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/fs.h> + #include <linux/semaphore.h> +#include <linux/cdev.h> +#include <linux/device.h> +#include <linux/ioctl.h> +#include <linux/slab.h> +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/spinlock_types.h> +#include <linux/workqueue.h> +#include <linux/irq.h> +#include <linux/gpio.h> +#include <mach/wmt_iomux.h> +#include "../../../video/backlight/wmt_bl.h" + +//----------------------------------------------------------------------------- +// Pin Declarations +//----------------------------------------------------------------------------- + +#define SUPPORT_ROCKCHIP 0 + +#if SUPPORT_ROCKCHIP +#include <linux/irq.h> +#include <mach/irqs.h> +//#include <mach/system.h> +#include <mach/hardware.h> +//#include <mach/board.h> +#include <mach/gpio.h> + +#define CTP_IRQ_PORT RK30_PIN1_PB7 +#define CTP_IRQ_MODE 0 +#define CTP_RST_PORT RK30_PIN1_PA7 +#define CTP_WAKEUP_PORT 0 + //1: B protocol +#define SCREEN_MAX_X (800) +#define SCREEN_MAX_Y (480) +#define ICN83XX_I2C_SCL 400*1000 + +#endif + +#define CTP_REPORT_PROTOCOL 1 //0: A protocol + +//----------------------------------------------------------------------------- +// Global CONSTANTS +//----------------------------------------------------------------------------- + +#define TOUCH_VIRTUAL_KEYS 0 +#define SUPPORT_PROC_FS 1 +#define SUPPORT_SYSFS 1 +#define SUPPORT_FW_UPDATE 1 +#define COMPILE_FW_WITH_DRIVER 0 +#define FORCE_UPDATA_FW 0 +#define SUPPORT_FW_CALIB 0 +#define SUPPORT_DELAYED_WORK 0 + +#define ICN83XX_NAME "chipone-ts" +#define ICN83XX_PROG_IIC_ADDR (0x60>>1) +#define ICN83XX_IIC_ADDR (0x80>>1) +#define CTP_NAME ICN83XX_NAME + +#define CTP_RESET_LOW_PERIOD (5) +#define CTP_RESET_HIGH_PERIOD (100) +#define CTP_WAKEUP_LOW_PERIOD (20) +#define CTP_WAKEUP_HIGH_PERIOD (50) +#define CTP_POLL_TIMER (16) /* ms delay between samples */ +#define CTP_START_TIMER (100) /* ms delay between samples */ + +#define POINT_NUM 5 +#define POINT_SIZE 7 + +#define TS_KEY_HOME 102 +#define TS_KEY_MENU 139 +#define TS_KEY_BACK 158 +#define TS_KEY_SEARCH 217 + +#define ICN_VIRTUAL_BUTTON_HOME 0x02 +#define ICN_VIRTUAL_BUTTON_MENU 0x01 +#define ICN_VIRTUAL_BUTTON_BACK 0x04 +#define ICN_VIRTUAL_BUTTON_SEARCH 0x08 + +#define IIC_RETRY_NUM 3 + +//ICN83XX_REG_PMODE +#define PMODE_ACTIVE 0x00 +#define PMODE_MONITOR 0x01 +#define PMODE_HIBERNATE 0x02 + +#define B_SIZE 32 +#define ENABLE_BYTE_CHECK +//#define WAKE_PIN 1 +//----------------------------------------------------------------------------- +// Macro DEFINITIONS +//----------------------------------------------------------------------------- +#define DBG_ICN83XX_TRACE +//#define DBG_ICN83XX_POINT +//#define DBG_ICN83XX_INFO +#define DBG_ICN83XX_ERROR +#define DBG_FLASH_INFO +#define DBG_FLASH_ERROR +#define DBG_OP_INFO +#define DBG_OP_ERROR +#define DBG_CALIB_INFO +#define DBG_CALIB_ERROR +//#define DBG_PROC_INFO +#define DBG_PROC_ERROR + + +#ifdef DBG_ICN83XX_TRACE +#define icn83xx_trace(fmt, args...) \ + do{ \ + printk(fmt, ##args); \ + }while(0) +#else +#define icn83xx_trace(fmt, args...) // +#endif + + +#ifdef DBG_ICN83XX_POINT +#define icn83xx_point_info(fmt, args...) \ + do{ \ + printk(fmt, ##args); \ + }while(0) +#else +#define icn83xx_point_info(fmt, args...) // +#endif + +#ifdef DBG_ICN83XX_INFO +#define icn83xx_info(fmt, args...) \ + do{ \ + printk(fmt, ##args); \ + }while(0) +#else +#define icn83xx_info(fmt, args...) // +#endif + +#ifdef DBG_ICN83XX_ERROR +#define icn83xx_error(fmt, args...) \ + do{ \ + printk(fmt, ##args); \ + }while(0) +#else +#define icn83xx_error(fmt, args...) // +#endif + +#ifdef DBG_FLASH_INFO +#define flash_info(fmt, args...) \ + do{ \ + printk(fmt, ##args); \ + }while(0) +#else +#define flash_info(fmt, args...) // +#endif + +#ifdef DBG_FLASH_ERROR +#define flash_error(fmt, args...) \ + do{ \ + printk(fmt, ##args); \ + }while(0) +#else +#define flash_error(fmt, args...) // +#endif + + +#ifdef DBG_OP_INFO +#define op_info(fmt, args...) \ + do{ \ + printk(fmt, ##args); \ + }while(0) +#else +#define op_info(fmt, args...) // +#endif +#ifdef DBG_OP_ERROR +#define op_error(fmt, args...) \ + do{ \ + printk(fmt, ##args); \ + }while(0) +#else +#define op_error(fmt, args...) // +#endif + + +#ifdef DBG_CALIB_INFO +#define calib_info(fmt, args...) \ + do{ \ + printk(fmt, ##args); \ + }while(0) +#else +#define calib_info(fmt, args...) // +#endif + +#ifdef DBG_CALIB_ERROR +#define calib_error(fmt, args...) \ + do{ \ + printk(fmt, ##args); \ + }while(0) +#else +#define calib_error(fmt, args...) // +#endif + + +#ifdef DBG_PROC_INFO +#define proc_info(fmt, args...) \ + do{ \ + printk(fmt, ##args); \ + }while(0) +#else +#define proc_info(fmt, args...) // +#endif + +#ifdef DBG_PROC_ERROR +#define proc_error(fmt, args...) \ + do{ \ + printk(fmt, ##args); \ + }while(0) +#else +#define proc_error(fmt, args...) // +#endif + +#define swap_ab(a,b) {char temp;temp=a;a=b;b=temp;} +#define U16LOBYTE(var) (*(unsigned char *) &var) +#define U16HIBYTE(var) (*(unsigned char *)((unsigned char *) &var + 1)) + + + +//----------------------------------------------------------------------------- +// Struct, Union and Enum DEFINITIONS +//----------------------------------------------------------------------------- +typedef struct _POINT_INFO +{ + unsigned char u8ID; + unsigned short u16PosX; // coordinate X, plus 4 LSBs for precision extension + unsigned short u16PosY; // coordinate Y, plus 4 LSBs for precision extension + unsigned char u8Pressure; + unsigned char u8EventId; +}POINT_INFO; + +struct icn83xx_ts_data { + struct i2c_client *client; + struct input_dev *input_dev; + struct work_struct pen_event_work; + struct delayed_work icn_delayed_work; + struct workqueue_struct *ts_workqueue; +#ifdef CONFIG_HAS_EARLYSUSPEND + struct early_suspend early_suspend; +#endif + struct hrtimer timer; + spinlock_t irq_lock; + struct semaphore sem; + + POINT_INFO point_info[POINT_NUM+1]; + int point_num; + int irq; + int irq_is_disable; + int use_irq; + int work_mode; + int screen_max_x; + int screen_max_y; + int revert_x_flag; + int revert_y_flag; + int exchange_x_y_flag; + int (*init_wakeup_hw)(void); +}; + +struct touch_param { + char fw_name[32]; + int irqgpio; + int rstgpio; + int panelres_x; + int panelres_y; + int xyswap; + int xdir; + int ydir; + int max_finger_num; + int force_download; + int earlysus_en; + int dbg; + int lcd_exchg; +}; + +#pragma pack(1) +typedef struct{ + unsigned char wr; //write read flagŁ¬0:R 1:W + unsigned char flag; //0: + unsigned char circle; //polling cycle + unsigned char times; //plling times + unsigned char retry; //I2C retry times + unsigned int data_len; //data length + unsigned char addr_len; //address length + unsigned char addr[2]; //address + unsigned char* data; //data pointer +}pack_head; +#pragma pack() + +#define DATA_LENGTH_UINT 512 +#define CMD_HEAD_LENGTH (sizeof(pack_head) - sizeof(unsigned char *)) +#define ICN83XX_ENTRY_NAME "icn83xx_tool" +enum icn83xx_ts_regs { + ICN83XX_REG_PMODE = 0x04, /* Power Consume Mode */ +}; + +typedef enum +{ + R_OK = 100, + R_FILE_ERR, + R_STATE_ERR, + R_ERASE_ERR, + R_PROGRAM_ERR, + R_VERIFY_ERR, +}E_UPGRADE_ERR_TYPE; + +//----------------------------------------------------------------------------- +// Global VARIABLES +//----------------------------------------------------------------------------- + + +//----------------------------------------------------------------------------- +// Function PROTOTYPES +//----------------------------------------------------------------------------- + +void icn83xx_ts_reset(void); +int icn83xx_i2c_rxdata(unsigned char addr, char *rxdata, int length); +int icn83xx_i2c_txdata(unsigned char addr, char *txdata, int length); +int icn83xx_write_reg(unsigned char addr, char para); +int icn83xx_read_reg(unsigned char addr, char *pdata); +int icn83xx_prog_i2c_rxdata(unsigned short addr, char *rxdata, int length); +int icn83xx_prog_i2c_txdata(unsigned short addr, char *txdata, int length); +int icn83xx_prog_write_reg(unsigned short addr, char para); +int icn83xx_prog_read_reg(unsigned short addr, char *pdata); +#if SUPPORT_FW_UPDATE + +int icn83xx_writeInfo(unsigned short addr, char value); +int icn83xx_readInfo(unsigned short addr, char *value); +int icn83xx_writeReg(unsigned short addr, char value); +int icn83xx_readReg(unsigned short addr, char *value); +int icn83xx_readVersion(void); +int icn83xx_changemode(char mode); +int icn83xx_readrawdata(char *buffer, char row, char length); +int icn83xx_readTP(char row_num, char column_num, char *buffer); +int icn83xx_scanTP(void); +void icn83xx_rawdatadump(short *mem, int size, char br); +void icn83xx_set_fw(int size, unsigned char *buf); +void icn83xx_memdump(char *mem, int size); +int icn83xx_checksum(int sum, char *buf, unsigned int size); +int icn83xx_update_status(int status); +int icn83xx_get_status(void); +int icn83xx_open_fw( char *fw); +int icn83xx_read_fw(int offset, int length, char *buf); +int icn83xx_close_fw(void); +int icn83xx_goto_progmode(void); +int icn83xx_check_progmod(void); +int icn83xx_uu(void); +void icn83xx_ll(void); +int icn83xx_op1(char info, unsigned short offset, unsigned int size); +int icn83xx_op2(char info, unsigned short offset, unsigned char * buffer, unsigned int size); +int icn83xx_op3(char info, unsigned short offset, unsigned char * buffer, unsigned int size); +short icn83xx_read_fw_Ver(char *fw); +E_UPGRADE_ERR_TYPE icn83xx_fw_update(char *fw); +#endif + +#if SUPPORT_FW_CALIB + +int icn83xx_checkrawdata(short *data, char num); +int icn83xx_readpara(char *TxOrder, char row, char *RxOrder, char column); +int icn83xx_writepara(char *TxOrder, char row, char *RxOrder, char column); +int icn83xx_readFB(char *FB, char num); +int icn83xx_writeFB(char *FB, char num); +int icn83xx_readDC(char *DC, char num); +int icn83xx_writeDC(char *DC, char num); +int icn83xx_readPhaseDelay(char *PD, char row, char length); +int icn83xx_writePhaseDelay(char *PD, char row, char length); +int icn83xx_changeDCflag(char flag); +int icn83xx_readVkmode(char *vkmode, char *vknum); +int icn83xx_setTarget(short target); +int icn83xx_setPeakGroup(short peak, short group); +int icn83xx_setDownUp(short down, short up); +int icn83xx_average(short *data, char num); + +int icn83xx_calib(char index, char *FB); +#endif + +#endif diff --git a/drivers/input/touchscreen/icn83xx_ts/icn83xx_fw.h b/drivers/input/touchscreen/icn83xx_ts/icn83xx_fw.h new file mode 100755 index 00000000..572bf1f3 --- /dev/null +++ b/drivers/input/touchscreen/icn83xx_ts/icn83xx_fw.h @@ -0,0 +1,3 @@ +static unsigned char icn83xx_fw[] = { + +};
\ No newline at end of file |