/*
* drivers/input/touchscreen/ft5x0x_ts.c
*
* FocalTech ft5x0x TouchScreen driver.
*
* Copyright (c) 2010 Focal tech Ltd.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* VERSION DATE AUTHOR Note
* 1.0 2010-01-05 WenFS only support mulititouch Wenfs 2010-10-01
* 2.0 2011-09-05 Duxx Add touch key, and project setting update, auto CLB command
*
*
*/
#include <linux/i2c.h>
#include <linux/input.h>
#include "ft5x06_ts.h"
#include <linux/earlysuspend.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
//#include <asm/jzsoc.h>
static struct i2c_client *this_client;
#define CONFIG_FT5X0X_MULTITOUCH 1
struct ts_event {
u16 au16_x[CFG_MAX_TOUCH_POINTS]; //x coordinate
u16 au16_y[CFG_MAX_TOUCH_POINTS]; //y coordinate
u8 au8_touch_event[CFG_MAX_TOUCH_POINTS]; //touch event: 0 -- down; 1-- contact; 2 -- contact
u8 au8_finger_id[CFG_MAX_TOUCH_POINTS]; //touch ID
u16 pressure;
u8 touch_point;
};
struct ft5x0x_ts_data {
struct input_dev *input_dev;
struct ts_event event;
struct work_struct pen_event_work;
struct workqueue_struct *ts_workqueue;
struct early_suspend early_suspend;
};
#if CFG_SUPPORT_TOUCH_KEY
int tsp_keycodes[CFG_NUMOFKEYS] ={
KEY_MENU,
KEY_HOME,
KEY_BACK,
KEY_SEARCH
};
char *tsp_keyname[CFG_NUMOFKEYS] ={
"Menu",
"Home",
"Back",
"Search"
};
static bool tsp_keystatus[CFG_NUMOFKEYS];
#endif
/***********************************************************************************************
Name : ft5x0x_i2c_rxdata
Input : *rxdata
*length
Output : ret
function :
***********************************************************************************************/
static int ft5x0x_i2c_rxdata(char *rxdata, int length)
{
int ret;
struct i2c_msg msgs[] = {
{
.addr = this_client->addr,
.flags = 0,
.len = 1,
.buf = rxdata,
},
{
.addr = this_client->addr,
.flags = I2C_M_RD,
.len = length,
.buf = rxdata,
},
};
//msleep(1);
ret = i2c_transfer(this_client->adapter, msgs, 2);
if (ret < 0)
pr_err("msg %s i2c read error: %d\n", __func__, ret);
return ret;
}
/***********************************************************************************************
Name :
Input :
Output :
function :
***********************************************************************************************/
static int ft5x0x_i2c_txdata(char *txdata, int length)
{
int ret;
struct i2c_msg msg[] = {
{
.addr = this_client->addr,
.flags = 0,
.len = length,
.buf = txdata,
},
};
//msleep(1);
ret = i2c_transfer(this_client->adapter, msg, 1);
if (ret < 0)
pr_err("%s i2c write error: %d\n", __func__, ret);
return ret;
}
/***********************************************************************************************
Name : ft5x0x_write_reg
Input : addr -- address
para -- parameter
Output :
function : write register of ft5x0x
***********************************************************************************************/
static int ft5x0x_write_reg(u8 addr, u8 para)
{
u8 buf[3];
int ret = -1;
buf[0] = addr;
buf[1] = para;
ret = ft5x0x_i2c_txdata(buf, 2);
if (ret < 0) {
pr_err("write reg failed! %#x ret: %d", buf[0], ret);
return -1;
}
return 0;
}
/***********************************************************************************************
Name : ft5x0x_read_reg
Input : addr
pdata
Output :
function : read register of ft5x0x
***********************************************************************************************/
static int ft5x0x_read_reg(u8 addr, u8 *pdata)
{
int ret;
u8 buf[2];
struct i2c_msg msgs[2];
//
buf[0] = addr; //register address
msgs[0].addr = this_client->addr;
msgs[0].flags = 0;
msgs[0].len = 1;
msgs[0].buf = buf;
msgs[1].addr = this_client->addr;
msgs[1].flags = I2C_M_RD;
msgs[1].len = 1;
msgs[1].buf = buf;
ret = i2c_transfer(this_client->adapter, msgs, 2);
if (ret < 0)
pr_err("msg %s i2c read error: %d\n", __func__, ret);
*pdata = buf[0];
return ret;
}
/***********************************************************************************************
Name : ft5x0x_read_fw_ver
Input : void
Output : firmware version
function : read TP firmware version
***********************************************************************************************/
static unsigned char ft5x0x_read_fw_ver(void)
{
unsigned char ver;
ft5x0x_read_reg(FT5X0X_REG_FIRMID, &ver);
return(ver);
}
#if 1 //upgrade related
typedef enum
{
ERR_OK,
ERR_MODE,
ERR_READID,
ERR_ERASE,
ERR_STATUS,
ERR_ECC,
ERR_DL_ERASE_FAIL,
ERR_DL_PROGRAM_FAIL,
ERR_DL_VERIFY_FAIL
}E_UPGRADE_ERR_TYPE;
typedef unsigned char FTS_BYTE; //8 bit
typedef unsigned short FTS_WORD; //16 bit
typedef unsigned int FTS_DWRD; //16 bit
typedef unsigned char FTS_BOOL; //8 bit
typedef struct _FTS_CTP_PROJECT_SETTING_T
{
unsigned char uc_i2C_addr; //I2C slave address (8 bit address)
unsigned char uc_io_voltage; //IO Voltage 0---3.3v; 1----1.8v
unsigned char uc_panel_factory_id; //TP panel factory ID
}FTS_CTP_PROJECT_SETTING_T;
#define FTS_NULL 0x0
#define FTS_TRUE 0x01
#define FTS_FALSE 0x0
#define I2C_CTPM_ADDRESS 0x70
void delay_qt_ms(unsigned long w_ms)
{
unsigned long i;
unsigned long j;
for (i = 0; i < w_ms; i++)
{
for (j = 0; j < 1000; j++)
{
udelay(1);
}
}
}
/*
[function]:
callback: read data from ctpm by i2c interface,implemented by special user;
[parameters]:
bt_ctpm_addr[in] :the address of the ctpm;
pbt_buf[out] :data buffer;
dw_lenth[in] :the length of the data buffer;
[return]:
FTS_TRUE :success;
FTS_FALSE :fail;
*/
FTS_BOOL i2c_read_interface(FTS_BYTE bt_ctpm_addr, FTS_BYTE* pbt_buf, FTS_DWRD dw_lenth)
{
int ret;
ret=i2c_master_recv(this_client, pbt_buf, dw_lenth);
if(ret<=0)
{
printk("[FTS]i2c_read_interface error\n");
return FTS_FALSE;
}
return FTS_TRUE;
}
/*
[function]:
callback: write data to ctpm by i2c interface,implemented by special user;
[parameters]:
bt_ctpm_addr[in] :the address of the ctpm;
pbt_buf[in] :data buffer;
dw_lenth[in] :the length of the data buffer;
[return]:
FTS_TRUE :success;
FTS_FALSE :fail;
*/
FTS_BOOL i2c_write_interface(FTS_BYTE bt_ctpm_addr, FTS_BYTE* pbt_buf, FTS_DWRD dw_lenth)
{
int ret;
ret=i2c_master_send(this_client, pbt_buf, dw_lenth);
if(ret<=0)
{
printk("[FTS]i2c_write_interface error line = %d, ret = %d\n", __LINE__, ret);
return FTS_FALSE;
}
return FTS_TRUE;
}
/*
[function]:
send a command to ctpm.
[parameters]:
btcmd[in] :command code;
btPara1[in] :parameter 1;
btPara2[in] :parameter 2;
btPara3[in] :parameter 3;
num[in] :the valid input parameter numbers, if only command code needed and no parameters followed,then the num is 1;
[return]:
FTS_TRUE :success;
FTS_FALSE :io fail;
*/
FTS_BOOL cmd_write(FTS_BYTE btcmd,FTS_BYTE btPara1,FTS_BYTE btPara2,FTS_BYTE btPara3,FTS_BYTE num