OSHW-DEIMOS/SOFTWARE/A64-TERES/linux-a64/drivers/input/touchscreen/aw5x06/AW5306_ts.c
Dimitar Gamishev f9b0e7a283 linux
2017-10-13 14:07:04 +03:00

2163 lines
54 KiB
C
Executable File

/**************************************************************************
* AW5306_ts.c
*
* AW5306 ALLWIN sample code version 1.0
*
* Create Date : 2012/06/07
*
* Modify Date :
*
* Create by : wuhaijun
*
**************************************************************************/
#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 <linux/file.h>
#include <linux/proc_fs.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <mach/irqs.h>
//#include <mach/system.h>
#include <mach/hardware.h>
#include <mach/sys_config.h>
//#include "ctp_platform_ops.h"
#include "AW5306_Drv.h"
#include "AW5306_userpara.h"
#define CONFIG_AW5306_MULTITOUCH (1)
#define FOR_TSLIB_TEST
//#define PRINT_INT_INFO
//#define PRINT_POINT_INFO
//#define DEBUG
//#define TOUCH_KEY_SUPPORT
#ifdef TOUCH_KEY_SUPPORT
//#define TOUCH_KEY_LIGHT_SUPPORT
#define TOUCH_KEY_FOR_EVB13
//#define TOUCH_KEY_FOR_ANGDA
#ifdef TOUCH_KEY_FOR_ANGDA
#define TOUCH_KEY_X_LIMIT (60000)
#define TOUCH_KEY_NUMBER (4)
#endif
#ifdef TOUCH_KEY_FOR_EVB13
#define TOUCH_KEY_LOWER_X_LIMIT (848)
#define TOUCH_KEY_HIGHER_X_LIMIT (852)
#define TOUCH_KEY_NUMBER (5)
#endif
#endif
#define TOUCH_KEY_NUMBER (5)
#define AW5306_NAME "aw5306_ts"//"synaptics_i2c_rmi"//"synaptics-rmi-ts"//
#define I2C_CTPM_ADDRESS (0x39)
#define CTP_NAME AW5306_NAME
struct i2c_dev{
struct list_head list;
struct i2c_adapter *adap;
struct device *dev;
};
static struct class *i2c_dev_class;
static LIST_HEAD (i2c_dev_list);
//static DEFINE_SPINLOCK(i2c_dev_list_lock);
static struct i2c_client *this_client;
#ifdef TOUCH_KEY_LIGHT_SUPPORT
static int gpio_light_hdle = 0;
#endif
#ifdef TOUCH_KEY_SUPPORT
static int key_tp = 0;
static int key_val = 0;
#endif
#ifdef PRINT_POINT_INFO
#define print_point_info(fmt, args...) \
do{ \
pr_info(fmt, ##args); \
}while(0)
#else
#define print_point_info(fmt, args...) //
#endif
#ifdef PRINT_INT_INFO
#define print_int_info(fmt, args...) \
do{ \
pr_info(fmt, ##args); \
}while(0)
#else
#define print_int_info(fmt, args...) //
#endif
#define CTP_IRQ_MODE (NEGATIVE_EDGE)
#define TS_RESET_LOW_PERIOD (1)
#define TS_INITIAL_HIGH_PERIOD (30)
#define TS_WAKEUP_LOW_PERIOD (20)
#define TS_WAKEUP_HIGH_PERIOD (20)
#define TS_POLL_DELAY (10) /* ms delay between samples */
#define TS_POLL_PERIOD (10) /* ms delay between samples */
//#define SCREEN_MAX_X (800)
//#define SCREEN_MAX_Y (480)
#define PRESS_MAX (255)
//#define AUTO_RUDUCEFRAME
#if 0
static void* __iomem gpio_addr = NULL;
static int gpio_int_hdle = 0;
static int gpio_wakeup_hdle = 0;
static int gpio_reset_hdle = 0;
static int gpio_wakeup_enable = 1;
static int gpio_reset_enable = 1;
static int store_pin_num;
#endif
int screen_max_x = 0;
int screen_max_y = 0;
#define SCREEN_MAX_X (screen_max_x)
#define SCREEN_MAX_Y (screen_max_y)
static int revert_x_flag = 0;
static int revert_y_flag = 0;
static int exchange_x_y_flag = 0;
//static int int_cfg_addr[]={PIO_INT_CFG0_OFFSET,PIO_INT_CFG1_OFFSET,
// PIO_INT_CFG2_OFFSET, PIO_INT_CFG3_OFFSET};
/* Addresses to scan */
//static union{
// unsigned short dirty_addr_buf[2];
// const unsigned short normal_i2c[2];
//}u_i2c_addr = {{0x00},};
static __u32 twi_id = 0;
//lkj====begin==================
#include <mach/irqs.h>
//#include <mach/system.h>
#include <mach/hardware.h>
#include <mach/gpio.h>
#include <linux/init-input.h>
#include <linux/gpio.h>
extern struct ctp_config_info config_info;
static struct i2c_client *this_client;
struct ctp_config_info config_info = {
.input_type = CTP_TYPE,
.name = NULL,
.int_number = 0,
};
#ifdef TOUCH_KEY_SUPPORT
static int key_tp = 0;
static int key_val = 0;
#endif
#define CTP_IRQ_NUMBER (config_info.irq_gpio_number)
//#define CTP_IRQ_MODE (TRIG_EDGE_NEGATIVE)
#define CTP_NAME AW5306_NAME
//#define SCREEN_MAX_X (screen_max_x)
//#define SCREEN_MAX_Y (screen_max_y)
//#define PRESS_MAX (255)
//static int screen_max_x = 0;
//static int screen_max_y = 0;
//static int revert_x_flag = 0;
//static int revert_y_flag = 0;
//static int exchange_x_y_flag = 0;
//static u32 int_handle = 0;
/* Addresses to scan */
static const unsigned short normal_i2c[2] = {0x38,I2C_CLIENT_END};
static const int chip_id_value[2] = {0xA8,0x0};
//static __u32 twi_id = 0;
static int ctp_get_system_config(void)
{
twi_id = config_info.twi_id;
screen_max_x = config_info.screen_max_x;
screen_max_y = config_info.screen_max_y;
revert_x_flag = config_info.revert_x_flag;
revert_y_flag = config_info.revert_y_flag;
exchange_x_y_flag = config_info.exchange_x_y_flag;
if((screen_max_x == 0) || (screen_max_y == 0)){
printk("%s:read config error!\n",__func__);
return 0;
}
return 1;
}
/**
* ctp_wakeup - function
*
*/
int ctp_wakeup(int status,int ms)
{
printk("***CTP*** %s:status:%d,ms = %d\n",__func__,status,ms);
if (status == 0) {
if(ms == 0) {
__gpio_set_value(config_info.wakeup_gpio.gpio, 0);
}else {
__gpio_set_value(config_info.wakeup_gpio.gpio, 0);
msleep(ms);
__gpio_set_value(config_info.wakeup_gpio.gpio, 1);
}
}
if (status == 1) {
if(ms == 0) {
__gpio_set_value(config_info.wakeup_gpio.gpio, 1);
}else {
__gpio_set_value(config_info.wakeup_gpio.gpio, 1);
msleep(ms);
__gpio_set_value(config_info.wakeup_gpio.gpio, 0);
}
}
msleep(5);
return 0;
}
static int ctp_detect(struct i2c_client *client, struct i2c_board_info *info)
{
struct i2c_adapter *adapter = client->adapter;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -ENODEV;
if(twi_id == adapter->nr)
{
pr_info("%s: Detected chip %s at adapter %d, address 0x%02x\n",
__func__, CTP_NAME, i2c_adapter_id(adapter), client->addr);
strlcpy(info->type, CTP_NAME, I2C_NAME_SIZE);
return 0;
}else{
return -ENODEV;
}
#if 0
if(twi_id == adapter->nr){
int ret = 0, i = 0;
if (client->addr == 0x38){
ret = i2c_smbus_read_byte_data(client,0x01);
printk("addr:0x%x,ret:0x%x\n",client->addr,ret);
while(chip_id_value[i++]){
if(ret == chip_id_value[i - 1]){
printk("found 0xa8\n");
strlcpy(info->type, CTP_NAME, I2C_NAME_SIZE);
return 0;
}
}
}
/*
else if (client->addr == 0x39) {
printk("addr is 0x39 \n");
strlcpy(info->type, CTP_NAME, I2C_NAME_SIZE);
return 0;
}
*/
printk("%s:I2C connection might be something wrong ! \n",__func__);
return -ENODEV;
}else{
return -ENODEV;
}
#endif
}
void __aeabi_unwind_cpp_pr0(void)
{
};
void __aeabi_unwind_cpp_pr1(void)
{
};
//lkj=======end===============
#if 0
///////////////////////////////////////////////
//specific tp related macro: need be configured for specific tp
#define CTP_IRQ_NO (gpio_int_info[0].port_num)
static user_gpio_set_t gpio_int_info[1];
/*
* ctp_get_pendown_state : get the int_line data state,
*
* return value:
* return PRESS_DOWN: if down
* return FREE_UP: if up,
* return 0: do not need process, equal free up.
*/
static int ctp_get_pendown_state(void)
{
unsigned int reg_val;
static int state = FREE_UP;
//get the input port state
reg_val = readl(gpio_addr + PIOH_DATA);
//pr_info("reg_val = %x\n",reg_val);
if(!(reg_val & (1<<CTP_IRQ_NO))){
state = PRESS_DOWN;
print_int_info("pen down. \n");
}else{ //touch panel is free up
state = FREE_UP;
print_int_info("free up. \n");
}
return state;
}
/**
* ctp_clear_penirq - clear int pending
*
*/
static void ctp_clear_penirq(void)
{
int reg_val;
//clear the IRQ_EINT29 interrupt pending
//pr_info("clear pend irq pending\n");
reg_val = readl(gpio_addr + PIO_INT_STAT_OFFSET);
//writel(reg_val,gpio_addr + PIO_INT_STAT_OFFSET);
//writel(reg_val&(1<<(IRQ_EINT21)),gpio_addr + PIO_INT_STAT_OFFSET);
if((reg_val = (reg_val&(1<<(CTP_IRQ_NO))))){
print_int_info("==CTP_IRQ_NO=\n");
writel(reg_val,gpio_addr + PIO_INT_STAT_OFFSET);
}
return;
}
/**
* ctp_set_irq_mode - according sysconfig's subkey "ctp_int_port" to config int port.
*
* return value:
* 0: success;
* others: fail;
*/
static int ctp_set_irq_mode(char *major_key , char *subkey, ext_int_mode int_mode)
{
int ret = 0;
__u32 reg_num = 0;
__u32 reg_addr = 0;
__u32 reg_val = 0;
//config gpio to int mode
pr_info("%s: config gpio to int mode. \n", __func__);
#ifndef SYSCONFIG_GPIO_ENABLE
#else
if(gpio_int_hdle){
gpio_release(gpio_int_hdle, 2);
}
gpio_int_hdle = gpio_request_ex(major_key, subkey);
if(!gpio_int_hdle){
pr_info("request tp_int_port failed. \n");
ret = -1;
goto request_tp_int_port_failed;
}
gpio_get_one_pin_status(gpio_int_hdle, gpio_int_info, subkey, 1);
pr_info("%s, %d: gpio_int_info, port = %d, port_num = %d. \n", __func__, __LINE__, \
gpio_int_info[0].port, gpio_int_info[0].port_num);
#endif
#ifdef AW_GPIO_INT_API_ENABLE
#else
pr_info(" INTERRUPT CONFIG\n");
reg_num = (gpio_int_info[0].port_num)%8;
reg_addr = (gpio_int_info[0].port_num)/8;
reg_val = readl(gpio_addr + int_cfg_addr[reg_addr]);
reg_val &= (~(7 << (reg_num * 4)));
reg_val |= (int_mode << (reg_num * 4));
writel(reg_val,gpio_addr+int_cfg_addr[reg_addr]);
ctp_clear_penirq();
reg_val = readl(gpio_addr+PIO_INT_CTRL_OFFSET);
reg_val |= (1 << (gpio_int_info[0].port_num));
writel(reg_val,gpio_addr+PIO_INT_CTRL_OFFSET);
udelay(1);
#endif
request_tp_int_port_failed:
return ret;
}
/**
* ctp_set_gpio_mode - according sysconfig's subkey "ctp_io_port" to config io port.
*
* return value:
* 0: success;
* others: fail;
*/
static int ctp_set_gpio_mode(void)
{
//int reg_val;
int ret = 0;
//config gpio to io mode
pr_info("%s: config gpio to io mode. \n", __func__);
#ifndef SYSCONFIG_GPIO_ENABLE
#else
if(gpio_int_hdle){
gpio_release(gpio_int_hdle, 2);
}
gpio_int_hdle = gpio_request_ex("ctp_para", "ctp_io_port");
if(!gpio_int_hdle){
pr_info("request ctp_io_port failed. \n");
ret = -1;
goto request_tp_io_port_failed;
}
#endif
return ret;
request_tp_io_port_failed:
return ret;
}
/**
* ctp_judge_int_occur - whether interrupt occur.
*
* return value:
* 0: int occur;
* others: no int occur;
*/
static int ctp_judge_int_occur(void)
{
//int reg_val[3];
int reg_val;
int ret = -1;
reg_val = readl(gpio_addr + PIO_INT_STAT_OFFSET);
if(reg_val&(1<<(CTP_IRQ_NO))){
ret = 0;
}
return ret;
}
/**
* ctp_free_platform_resource - corresponding with ctp_init_platform_resource
*
*/
static void ctp_free_platform_resource(void)
{
if(gpio_addr){
iounmap(gpio_addr);
}
if(gpio_int_hdle){
gpio_release(gpio_int_hdle, 2);
}
if(gpio_wakeup_hdle){
gpio_release(gpio_wakeup_hdle, 2);
}
if(gpio_reset_hdle){
gpio_release(gpio_reset_hdle, 2);
}
return;
}
/**
* ctp_init_platform_resource - initialize platform related resource
* return value: 0 : success
* -EIO : i/o err.
*
*/
static int ctp_init_platform_resource(void)
{
int ret = 0;
gpio_addr = ioremap(PIO_BASE_ADDRESS, PIO_RANGE_SIZE);
//pr_info("%s, gpio_addr = 0x%x. \n", __func__, gpio_addr);
if(!gpio_addr) {
ret = -EIO;
goto exit_ioremap_failed;
}
// gpio_wakeup_enable = 1;
gpio_wakeup_hdle = gpio_request_ex("ctp_para", "ctp_wakeup");
if(!gpio_wakeup_hdle) {
pr_warning("%s: tp_wakeup request gpio fail!\n", __func__);
gpio_wakeup_enable = 0;
}
gpio_reset_hdle = gpio_request_ex("ctp_para", "ctp_reset");
if(!gpio_reset_hdle) {
pr_warning("%s: tp_reset request gpio fail!\n", __func__);
gpio_reset_enable = 0;
}
return ret;
exit_ioremap_failed:
ctp_free_platform_resource();
return ret;
}
/**
* ctp_fetch_sysconfig_para - get config info from sysconfig.fex file.
* return value:
* = 0; success;
* < 0; err
*/
static int ctp_fetch_sysconfig_para(void)
{
int ret = -1;
int ctp_used = -1;
char name[I2C_NAME_SIZE];
__u32 twi_addr = 0;
//__u32 twi_id = 0;
script_parser_value_type_t type = SCIRPT_PARSER_VALUE_TYPE_STRING;
pr_info("%s. \n", __func__);
if(SCRIPT_PARSER_OK != script_parser_fetch("ctp_para", "ctp_used", &ctp_used, 1)){
pr_err("%s: script_parser_fetch err. \n", __func__);
goto script_parser_fetch_err;
}
if(1 != ctp_used){
pr_err("%s: ctp_unused. \n", __func__);
//ret = 1;
return ret;
}
if(SCRIPT_PARSER_OK != script_parser_fetch_ex("ctp_para", "ctp_name", (int *)(&name), &type, sizeof(name)/sizeof(int))){
pr_err("%s: script_parser_fetch err. \n", __func__);
goto script_parser_fetch_err;
}
if(strcmp(CTP_NAME, name)){
pr_err("%s: name %s does not match CTP_NAME. \n", __func__, name);
pr_err(CTP_NAME);
//ret = 1;
return ret;
}
if(SCRIPT_PARSER_OK != script_parser_fetch("ctp_para", "ctp_twi_addr", &twi_addr, sizeof(twi_addr)/sizeof(__u32))){
pr_err("%s: script_parser_fetch err. \n", name);
goto script_parser_fetch_err;
}
//big-endian or small-endian?
//pr_info("%s: before: ctp_twi_addr is 0x%x, dirty_addr_buf: 0x%hx. dirty_addr_buf[1]: 0x%hx \n", __func__, twi_addr, u_i2c_addr.dirty_addr_buf[0], u_i2c_addr.dirty_addr_buf[1]);
u_i2c_addr.dirty_addr_buf[0] = twi_addr;
u_i2c_addr.dirty_addr_buf[1] = I2C_CLIENT_END;
pr_info("%s: after: ctp_twi_addr is 0x%x, dirty_addr_buf: 0x%hx. dirty_addr_buf[1]: 0x%hx \n", __func__, twi_addr, u_i2c_addr.dirty_addr_buf[0], u_i2c_addr.dirty_addr_buf[1]);
//pr_info("%s: after: ctp_twi_addr is 0x%x, u32_dirty_addr_buf: 0x%hx. u32_dirty_addr_buf[1]: 0x%hx \n", __func__, twi_addr, u32_dirty_addr_buf[0],u32_dirty_addr_buf[1]);
if(SCRIPT_PARSER_OK != script_parser_fetch("ctp_para", "ctp_twi_id", &twi_id, sizeof(twi_id)/sizeof(__u32))){
pr_err("%s: script_parser_fetch err. \n", name);
goto script_parser_fetch_err;
}
pr_info("%s: ctp_twi_id is %d. \n", __func__, twi_id);
if(SCRIPT_PARSER_OK != script_parser_fetch("ctp_para", "ctp_screen_max_x", &screen_max_x, 1)){
pr_err("%s: script_parser_fetch err. \n", __func__);
goto script_parser_fetch_err;
}
pr_info("%s: screen_max_x = %d. \n", __func__, screen_max_x);
if(SCRIPT_PARSER_OK != script_parser_fetch("ctp_para", "ctp_screen_max_y", &screen_max_y, 1)){
pr_err("%s: script_parser_fetch err. \n", __func__);
goto script_parser_fetch_err;
}
pr_info("%s: screen_max_y = %d. \n", __func__, screen_max_y);
if(SCRIPT_PARSER_OK != script_parser_fetch("ctp_para", "ctp_revert_x_flag", &revert_x_flag, 1)){
pr_err("%s: script_parser_fetch err. \n", __func__);
goto script_parser_fetch_err;
}
pr_info("%s: revert_x_flag = %d. \n", __func__, revert_x_flag);
if(SCRIPT_PARSER_OK != script_parser_fetch("ctp_para", "ctp_revert_y_flag", &revert_y_flag, 1)){
pr_err("%s: script_parser_fetch err. \n", __func__);
goto script_parser_fetch_err;
}
pr_info("%s: revert_y_flag = %d. \n", __func__, revert_y_flag);
if(SCRIPT_PARSER_OK != script_parser_fetch("ctp_para", "ctp_exchange_x_y_flag", &exchange_x_y_flag, 1)){
pr_err("AW5306_ts: script_parser_fetch err. \n");
goto script_parser_fetch_err;
}
pr_info("%s: exchange_x_y_flag = %d. \n", __func__, exchange_x_y_flag);
return 0;
script_parser_fetch_err:
pr_notice("=========script_parser_fetch_err============\n");
return ret;
}
static void ft_ctp_reset(void)
{
if(1 == gpio_wakeup_enable){
pr_info("%s. \n", __func__);
if(EGPIO_SUCCESS != gpio_write_one_pin_value(gpio_wakeup_hdle, 0, "ctp_wakeup")){
pr_info("%s: err when operate gpio. \n", __func__);
}
mdelay(TS_WAKEUP_LOW_PERIOD);
if(EGPIO_SUCCESS != gpio_write_one_pin_value(gpio_wakeup_hdle, 1, "ctp_wakeup")){
pr_info("%s: err when operate gpio. \n", __func__);
}
mdelay(TS_WAKEUP_HIGH_PERIOD);
}
return;
}
/**
* ctp_reset - function
*
*/
static void ctp_reset(void)
{
if(gpio_reset_enable){
pr_info("%s. \n", __func__);
if(EGPIO_SUCCESS != gpio_write_one_pin_value(gpio_reset_hdle, 1, "ctp_reset")){
pr_info("%s: err when operate gpio. \n", __func__);
}
mdelay(TS_RESET_LOW_PERIOD);
if(EGPIO_SUCCESS != gpio_write_one_pin_value(gpio_reset_hdle, 0, "ctp_reset")){
pr_info("%s: err when operate gpio. \n", __func__);
}
mdelay(TS_INITIAL_HIGH_PERIOD);
}
}
/**
* ctp_wakeup - function
*
*/
static void ctp_wakeup(void)
{
if(1 == gpio_wakeup_enable){
pr_info("%s. \n", __func__);
if(EGPIO_SUCCESS != gpio_write_one_pin_value(gpio_wakeup_hdle, 1, "ctp_wakeup")){
pr_info("%s: err when operate gpio. \n", __func__);
}
mdelay(TS_WAKEUP_LOW_PERIOD);
if(EGPIO_SUCCESS != gpio_write_one_pin_value(gpio_wakeup_hdle, 0, "ctp_wakeup")){
pr_info("%s: err when operate gpio. \n", __func__);
}
mdelay(TS_WAKEUP_HIGH_PERIOD);
}
return;
}
/**
* ctp_detect - Device detection callback for automatic device creation
* return value:
* = 0; success;
* < 0; err
*/
int ctp_detect(struct i2c_client *client, struct i2c_board_info *info)
{
struct i2c_adapter *adapter = client->adapter;
if(twi_id == adapter->nr)
{
pr_info("%s: Detected chip %s at adapter %d, address 0x%02x\n",
__func__, CTP_NAME, i2c_adapter_id(adapter), client->addr);
strlcpy(info->type, CTP_NAME, I2C_NAME_SIZE);
return 0;
}else{
return -ENODEV;
}
}
////////////////////////////////////////////////////////////////
static struct ctp_platform_ops ctp_ops = {
.get_pendown_state = ctp_get_pendown_state,
.clear_penirq = ctp_clear_penirq,
.set_irq_mode = ctp_set_irq_mode,
.set_gpio_mode = ctp_set_gpio_mode,
.judge_int_occur = ctp_judge_int_occur,
.init_platform_resource = ctp_init_platform_resource,
.free_platform_resource = ctp_free_platform_resource,
.fetch_sysconfig_para = ctp_fetch_sysconfig_para,
.ts_reset = ctp_reset,
.ts_wakeup = ctp_wakeup,
.ts_detect = ctp_detect,
};
#endif
int fts_ctpm_fw_upgrade_with_i_file(void);
#if 0
static struct i2c_dev *i2c_dev_get_by_minor(unsigned index)
{
struct i2c_dev *i2c_dev;
spin_lock(&i2c_dev_list_lock);
list_for_each_entry(i2c_dev,&i2c_dev_list,list){
pr_info("--line = %d ,i2c_dev->adapt->nr = %d,index = %d.\n",__LINE__,i2c_dev->adap->nr,index);
if(i2c_dev->adap->nr == index){
goto found;
}
}
i2c_dev = NULL;
found:
spin_unlock(&i2c_dev_list_lock);
return i2c_dev ;
}
#endif
struct ts_event {
int x[5];
int y[5];
int pressure;
int touch_ID[5];
int touch_point;
int pre_point;
};
struct AW5306_ts_data {
struct input_dev *input_dev;
struct ts_event event;
struct work_struct pen_event_work;
struct workqueue_struct *ts_workqueue;
#ifdef CONFIG_HAS_EARLYSUSPEND
struct early_suspend early_suspend;
#endif
struct timer_list touch_timer;
};
/* ---------------------------------------------------------------------
*
* Focal Touch panel upgrade related driver
*
*
----------------------------------------------------------------------*/
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
#define FTS_NULL 0x0
#define FTS_TRUE 0x01
#define FTS_FALSE 0x0
//extern char AW5306_CLB();
//extern void AW5306_CLB_GetCfg();
extern STRUCTCALI AW_Cali;
extern AW5306_UCF AWTPCfg;
extern STRUCTBASE AW_Base;
extern short Diff[NUM_TX][NUM_RX];
extern short adbDiff[NUM_TX][NUM_RX];
extern short AWDeltaData[32];
static unsigned char suspend_flag=0; //0: sleep out; 1: sleep in
static short tp_idlecnt = 0;
static char tp_SlowMode = 1;
int AW_nvram_read(char *filename, char *buf, ssize_t len, int offset)
{
struct file *fd;
//ssize_t ret;
int retLen = -1;
mm_segment_t old_fs = get_fs();
set_fs(KERNEL_DS);
fd = filp_open(filename, O_RDONLY, 0);
if(IS_ERR(fd)) {
printk("[AW5306][nvram_read] : failed to open!!\n");
return -1;
}
do{
if ((fd->f_op == NULL) || (fd->f_op->read == NULL))
{
printk("[AW5306][nvram_read] : file can not be read!!\n");
break;
}
if (fd->f_pos != offset) {
if (fd->f_op->llseek) {
if(fd->f_op->llseek(fd, offset, 0) != offset) {
printk("[AW5306][nvram_read] : failed to seek!!\n");
break;
}
} else {
fd->f_pos = offset;
}
}
retLen = fd->f_op->read(fd,
buf,
len,
&fd->f_pos);
}while(false);
filp_close(fd, NULL);
set_fs(old_fs);
return retLen;
}
int AW_nvram_write(char *filename, char *buf, ssize_t len, int offset)
{
struct file *fd;
//ssize_t ret;
int retLen = -1;
mm_segment_t old_fs = get_fs();
set_fs(KERNEL_DS);
fd = filp_open(filename, O_WRONLY|O_CREAT, 0666);
if(IS_ERR(fd)) {
printk("[AW5306][nvram_write] : failed to open!!\n");
return -1;
}
do{
if ((fd->f_op == NULL) || (fd->f_op->write == NULL))
{
printk("[AW5306][nvram_write] : file can not be write!!\n");
break;
} /* End of if */
if (fd->f_pos != offset) {
if (fd->f_op->llseek) {
if(fd->f_op->llseek(fd, offset, 0) != offset) {
printk("[AW5306][nvram_write] : failed to seek!!\n");
break;
}
} else {
fd->f_pos = offset;
}
}
retLen = fd->f_op->write(fd,
buf,
len,
&fd->f_pos);
}while(false);
filp_close(fd, NULL);
set_fs(old_fs);
return retLen;
}
int AW_I2C_WriteByte(u8 addr, u8 para)
{
int ret;
u8 buf[3];
struct i2c_msg msg[] = {
{
.addr = this_client->addr,
.flags = 0,
.len = 2,
.buf = buf,
},
};
buf[0] = addr;
buf[1] = para;
ret = i2c_transfer(this_client->adapter, msg, 1);
return ret;
}
unsigned char AW_I2C_ReadByte(u8 addr)
{
int ret;
u8 buf[2] = {0};
struct i2c_msg msgs[] = {
{
.addr = this_client->addr,
.flags = 0,
.len = 1,
.buf = buf,
},
{
.addr = this_client->addr,
.flags = I2C_M_RD,
.len = 1,
.buf = buf,
},
};
buf[0] = addr;
//msleep(1);
ret = i2c_transfer(this_client->adapter, msgs, 2);
return buf[0];
}
unsigned char AW_I2C_ReadXByte( unsigned char *buf, unsigned char addr, unsigned short len)
{
int ret,i;
u8 rdbuf[512] = {0};
struct i2c_msg msgs[] = {
{
.addr = this_client->addr,
.flags = 0,
.len = 1,
.buf = rdbuf,
},
{
.addr = this_client->addr,
.flags = I2C_M_RD,
.len = len,
.buf = rdbuf,
},
};
rdbuf[0] = addr;
//msleep(1);
ret = i2c_transfer(this_client->adapter, msgs, 2);
if (ret < 0)
pr_err("msg %s i2c read error: %d\n", __func__, ret);
for(i = 0; i < len; i++)
{
buf[i] = rdbuf[i];
}
return ret;
}
unsigned char AW_I2C_WriteXByte( unsigned char *buf, unsigned char addr, unsigned short len)
{
int ret,i;
u8 wdbuf[512] = {0};
struct i2c_msg msgs[] = {
{
.addr = this_client->addr,
.flags = 0,
.len = len+1,
.buf = wdbuf,
}
};
wdbuf[0] = addr;
for(i = 0; i < len; i++)
{
wdbuf[i+1] = buf[i];
}
//msleep(1);
ret = i2c_transfer(this_client->adapter, msgs, 1);
if (ret < 0)
pr_err("msg %s i2c read error: %d\n", __func__, ret);
return ret;
}
void AW_Sleep(unsigned int msec)
{
msleep(msec);
}
static ssize_t AW5306_get_Cali(struct device* cd,struct device_attribute *attr, char* buf);
static ssize_t AW5306_set_Cali(struct device* cd,struct device_attribute *attr, const char *buf, size_t count);
static ssize_t AW5306_get_reg(struct device* cd,struct device_attribute *attr, char* buf);
static ssize_t AW5306_write_reg(struct device* cd,struct device_attribute *attr, const char *buf, size_t count);
static ssize_t AW5306_get_Base(struct device* cd,struct device_attribute *attr, char* buf);
static ssize_t AW5306_get_Diff(struct device* cd,struct device_attribute *attr, char* buf);
static ssize_t AW5306_get_adbBase(struct device* cd,struct device_attribute *attr, char* buf);
static ssize_t AW5306_get_adbDiff(struct device* cd,struct device_attribute *attr, char* buf);
static ssize_t AW5306_get_FreqScan(struct device* cd,struct device_attribute *attr, char* buf);
static ssize_t AW5306_Set_FreqScan(struct device* cd, struct device_attribute *attr, const char* buf, size_t len);
static DEVICE_ATTR(cali, S_IRUGO | S_IWUSR, AW5306_get_Cali, AW5306_set_Cali);
static DEVICE_ATTR(readreg, S_IRUGO | S_IWUSR, AW5306_get_reg, AW5306_write_reg);
static DEVICE_ATTR(base, S_IRUGO | S_IWUSR, AW5306_get_Base, NULL);
static DEVICE_ATTR(diff, S_IRUGO | S_IWUSR, AW5306_get_Diff, NULL);
static DEVICE_ATTR(adbbase, S_IRUGO | S_IWUSR, AW5306_get_adbBase, NULL);
static DEVICE_ATTR(adbdiff, S_IRUGO | S_IWUSR, AW5306_get_adbDiff, NULL);
static DEVICE_ATTR(freqscan, S_IRUGO | S_IWUSR, AW5306_get_FreqScan, AW5306_Set_FreqScan);
static ssize_t AW5306_get_Cali(struct device* cd,struct device_attribute *attr, char* buf)
{
unsigned char i,j;
ssize_t len = 0;
len += snprintf(buf+len, PAGE_SIZE-len,"*****AW5306 Calibrate data*****\n");
len += snprintf(buf+len, PAGE_SIZE-len,"TXOFFSET:");
for(i=0;i<11;i++)
{
len += snprintf(buf+len, PAGE_SIZE-len, "0x%02X ", AW_Cali.TXOFFSET[i]);
}
len += snprintf(buf+len, PAGE_SIZE-len, "\n");
len += snprintf(buf+len, PAGE_SIZE-len, "RXOFFSET:");
for(i=0;i<6;i++)
{
len += snprintf(buf+len, PAGE_SIZE-len, "0x%02X ", AW_Cali.RXOFFSET[i]);
}
len += snprintf(buf+len, PAGE_SIZE-len, "\n");
len += snprintf(buf+len, PAGE_SIZE-len, "TXCAC:");
for(i=0;i<21;i++)
{
len += snprintf(buf+len, PAGE_SIZE-len, "0x%02X ", AW_Cali.TXCAC[i]);
}
len += snprintf(buf+len, PAGE_SIZE-len, "\n");
len += snprintf(buf+len, PAGE_SIZE-len, "RXCAC:");
for(i=0;i<12;i++)
{
len += snprintf(buf+len, PAGE_SIZE-len, "0x%02X ", AW_Cali.RXCAC[i]);
}
len += snprintf(buf+len, PAGE_SIZE-len, "\n");
len += snprintf(buf+len, PAGE_SIZE-len, "TXGAIN:");
for(i=0;i<21;i++)
{
len += snprintf(buf+len, PAGE_SIZE-len, "0x%02X ", AW_Cali.TXGAIN[i]);
}
len += snprintf(buf+len, PAGE_SIZE-len, "\n");
for(i=0;i<AWTPCfg.TX_LOCAL;i++)
{
for(j=0;j<AWTPCfg.RX_LOCAL;j++)
{
len += snprintf(buf+len, PAGE_SIZE-len, "%4d ", AW_Cali.SOFTOFFSET[i][j]);
}
len += snprintf(buf+len, PAGE_SIZE-len, "\n");
}
return len;
}
static ssize_t AW5306_set_Cali(struct device* cd,struct device_attribute *attr, const char *buf, size_t count)
{
struct AW5306_ts_data *data = i2c_get_clientdata(this_client);
unsigned long on_off = simple_strtoul(buf, NULL, 10);
if(on_off == 1)
{
suspend_flag = 1;
AW_Sleep(50);
TP_Force_Calibration();
AW5306_TP_Reinit();
tp_idlecnt = 0;
tp_SlowMode = 0;
suspend_flag = 0;
data->touch_timer.expires = jiffies + HZ/AWTPCfg.FAST_FRAME;
add_timer(&data->touch_timer);
}
return count;
}
static ssize_t AW5306_get_adbBase(struct device* cd,struct device_attribute *attr, char* buf)
{
unsigned char i,j;
ssize_t len = 0;
len += snprintf(buf+len, PAGE_SIZE-len, "base: \n");
for(i=0;i< AWTPCfg.TX_LOCAL;i++)
{
for(j=0;j<AWTPCfg.RX_LOCAL;j++)
{
len += snprintf(buf+len, PAGE_SIZE-len, "%4d, ",AW_Base.Base[i][j]+AW_Cali.SOFTOFFSET[i][j]);
}
len += snprintf(buf+len, PAGE_SIZE-len, "\n");
}
return len;
}
static ssize_t AW5306_get_Base(struct device* cd,struct device_attribute *attr, char* buf)
{
unsigned char i,j;
ssize_t len = 0;
*(buf+len) = AWTPCfg.TX_LOCAL;
len++;
*(buf+len) = AWTPCfg.RX_LOCAL;
len++;
for(i=0;i< AWTPCfg.TX_LOCAL;i++)
{
for(j=0;j<AWTPCfg.RX_LOCAL;j++)
{
*(buf+len) = (char)(((AW_Base.Base[i][j]+AW_Cali.SOFTOFFSET[i][j]) & 0xFF00)>>8);
len++;
*(buf+len) = (char)((AW_Base.Base[i][j]+AW_Cali.SOFTOFFSET[i][j]) & 0x00FF);
len++;
}
}
return len;
}
static ssize_t AW5306_get_adbDiff(struct device* cd,struct device_attribute *attr, char* buf)
{
unsigned char i,j;
ssize_t len = 0;
len += snprintf(buf+len, PAGE_SIZE-len, "Diff: \n");
for(i=0;i< AWTPCfg.TX_LOCAL;i++)
{
for(j=0;j<AWTPCfg.RX_LOCAL;j++)
{
len += snprintf(buf+len, PAGE_SIZE-len, "%4d, ",adbDiff[i][j]);
}
len += snprintf(buf+len, PAGE_SIZE-len, "\n");
}
return len;
}
static ssize_t AW5306_get_Diff(struct device* cd,struct device_attribute *attr, char* buf)
{
unsigned char i,j;
ssize_t len = 0;
*(buf+len) = AWTPCfg.TX_LOCAL;
len++;
*(buf+len) = AWTPCfg.RX_LOCAL;
len++;
for(i=0;i< AWTPCfg.TX_LOCAL;i++)
{
for(j=0;j<AWTPCfg.RX_LOCAL;j++)
{
*(buf+len) = (char)((adbDiff[i][j] & 0xFF00)>>8);
len++;
*(buf+len) = (char)(adbDiff[i][j] & 0x00FF);
len++;
}
}
return len;
}
static ssize_t AW5306_get_FreqScan(struct device* cd,struct device_attribute *attr, char* buf)
{
unsigned char i;
ssize_t len = 0;
for(i=0;i< 32;i++)
{
//*(buf+len) = (char)((AWDeltaData[i] & 0xFF00)>>8);
//len++;
//*(buf+len) = (char)(AWDeltaData[i] & 0x00FF);
//len++;
len += snprintf(buf+len, PAGE_SIZE-len, "%4d, ",AWDeltaData[i]);
}
len += snprintf(buf+len, PAGE_SIZE-len, "\n");
return len;
}
static ssize_t AW5306_Set_FreqScan(struct device* cd, struct device_attribute *attr,
const char* buf, size_t len)
{
struct AW5306_ts_data *data = i2c_get_clientdata(this_client);
unsigned long Basefreq = simple_strtoul(buf, NULL, 10);
if(Basefreq < 10)
{
suspend_flag = 1;
AW_Sleep(50);
FreqScan(Basefreq);
AW5306_TP_Reinit();
tp_idlecnt = 0;
tp_SlowMode = 0;
suspend_flag = 0;
data->touch_timer.expires = jiffies + HZ/AWTPCfg.FAST_FRAME;
add_timer(&data->touch_timer);
}
return len;
}
static ssize_t AW5306_get_reg(struct device* cd,struct device_attribute *attr, char* buf)
{
struct AW5306_ts_data *data = i2c_get_clientdata(this_client);
u8 reg_val[128];
ssize_t len = 0;
u8 i;
suspend_flag = 1;
AW_Sleep(50);
AW_I2C_ReadXByte(reg_val,0,127);
AW5306_TP_Reinit();
tp_idlecnt = 0;
tp_SlowMode = 0;
suspend_flag = 0;
data->touch_timer.expires = jiffies + HZ/AWTPCfg.FAST_FRAME;
add_timer(&data->touch_timer);
for(i=0;i<0x7F;i++)
{
reg_val[0] = AW_I2C_ReadByte(i);
len += snprintf(buf+len, PAGE_SIZE-len, "reg%02X = 0x%02X, ", i,reg_val[0]);
}
return len;
}
static ssize_t AW5306_write_reg(struct device* cd,struct device_attribute *attr, const char *buf, size_t count)
{
struct AW5306_ts_data *data = i2c_get_clientdata(this_client);
int databuf[2];
if(2 == sscanf(buf, "%d %d", &databuf[0], &databuf[1]))
{
suspend_flag = 1;
AW_Sleep(50);
AW_I2C_WriteByte((u8)databuf[0],(u8)databuf[1]);
AW5306_TP_Reinit();
tp_idlecnt = 0;
tp_SlowMode = 0;
suspend_flag = 0;
data->touch_timer.expires = jiffies + HZ/AWTPCfg.FAST_FRAME;
add_timer(&data->touch_timer);
}
else
{
printk("invalid content: '%s', length = %d\n", buf, count);
}
return count;
}
static int AW5306_create_sysfs(struct i2c_client *client)
{
int err;
struct device *dev = &(client->dev);
//TS_DBG("%s", __func__);
err = device_create_file(dev, &dev_attr_cali);
err = device_create_file(dev, &dev_attr_readreg);
err = device_create_file(dev, &dev_attr_base);
err = device_create_file(dev, &dev_attr_diff);
err = device_create_file(dev, &dev_attr_adbbase);
err = device_create_file(dev, &dev_attr_adbdiff);
err = device_create_file(dev, &dev_attr_freqscan);
return err;
}
static void AW5306_ts_release(void)
{
struct AW5306_ts_data *data = i2c_get_clientdata(this_client);
#ifdef CONFIG_AW5306_MULTITOUCH
#ifdef TOUCH_KEY_SUPPORT
if(1 == key_tp){
if(key_val == 1){
input_report_key(data->input_dev, KEY_MENU, 0);
input_sync(data->input_dev);
}
else if(key_val == 2){
input_report_key(data->input_dev, KEY_BACK, 0);
input_sync(data->input_dev);
// printk("===KEY 2 upupupupupu===++=\n");
}
else if(key_val == 3){
input_report_key(data->input_dev, KEY_SEARCH, 0);
input_sync(data->input_dev);
// printk("===KEY 3 upupupupupu===++=\n");
}
else if(key_val == 4){
input_report_key(data->input_dev, KEY_HOMEPAGE, 0);
input_sync(data->input_dev);
// printk("===KEY 4 upupupupupu===++=\n");
}
else if(key_val == 5){
input_report_key(data->input_dev, KEY_VOLUMEDOWN, 0);
input_sync(data->input_dev);
// printk("===KEY 5 upupupupupu===++=\n");
}
else if(key_val == 6){
input_report_key(data->input_dev, KEY_VOLUMEUP, 0);
input_sync(data->input_dev);
// printk("===KEY 6 upupupupupu===++=\n");
}
// input_report_key(data->input_dev, key_val, 0);
//printk("Release Key = %d\n",key_val);
//printk("Release Keyi+++++++++++++++++++++++++++++\n");
} else{
input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR, 0);
}
#else
input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR, 0);
#endif
#else
input_report_abs(data->input_dev, ABS_PRESSURE, 0);
input_report_key(data->input_dev, BTN_TOUCH, 0);
#endif
input_sync(data->input_dev);
return;
}
static int AW5306_read_data(void)
{
struct AW5306_ts_data *data = i2c_get_clientdata(this_client);
struct ts_event *event = &data->event;
int Pevent;
int i = 0;
AW5306_TouchProcess();
//memset(event, 0, sizeof(struct ts_event));
event->touch_point = AW5306_GetPointNum();
for(i=0;i<event->touch_point;i++)
{
AW5306_GetPoint(&event->x[i],&event->y[i],&event->touch_ID[i],&Pevent,i);
swap(event->x[i], event->y[i]);
// printk("AW5306key%d = %d,%d,%d \n",i,event->x[i],event->y[i],event->touch_ID[i] );
}
if (event->touch_point == 0)
{
if(tp_idlecnt <= AWTPCfg.FAST_FRAME*5)
{
tp_idlecnt++;
}
if(tp_idlecnt > AWTPCfg.FAST_FRAME*5)
{
tp_SlowMode = 1;
}
if (event->pre_point != 0)
{
AW5306_ts_release();
event->pre_point = 0;
}
return 1;
}
else
{
tp_SlowMode = 0;
tp_idlecnt = 0;
event->pre_point = event->touch_point;
#ifdef CONFIG_AW5306_MULTITOUCH
// printk("tmp =%d\n",store_pin_num);
// printk("touch_point=%d\n",event->touch_point);
switch (event->touch_point) {
case 5:
if(1 == exchange_x_y_flag){
swap(event->x[4], event->y[4]);
}
if(0 == revert_x_flag){
event->x[4] = SCREEN_MAX_X - event->x[4];
}
if(1 == revert_y_flag){
event->y[4] = SCREEN_MAX_Y - event->y[4];
}
case 4:
if(1 == exchange_x_y_flag){
swap(event->x[3], event->y[3]);
}
if(0 == revert_x_flag){
event->x[3] = SCREEN_MAX_X - event->x[3];
}
if(1 == revert_y_flag){
event->y[3] = SCREEN_MAX_Y - event->y[3];
}
case 3:
if(1 == exchange_x_y_flag){
swap(event->x[2], event->y[2]);
}
if(0 == revert_x_flag){
event->x[2] = SCREEN_MAX_X - event->x[2];
}
if(1 == revert_y_flag){
event->y[2] = SCREEN_MAX_Y - event->y[2];
}
case 2:
if(1 == exchange_x_y_flag){
swap(event->x[1], event->y[1]);
}
if(0== revert_x_flag){
event->x[1] = SCREEN_MAX_X - event->x[1];
}
if(1 == revert_y_flag){
event->y[1] = SCREEN_MAX_Y - event->y[1];
}
case 1:
#ifdef TOUCH_KEY_FOR_ANGDA
if(event->x[0] < TOUCH_KEY_X_LIMIT)
{
if(0 == revert_x_flag){
event->x[0] = SCREEN_MAX_X - event->x[0];
}
if(1 == revert_y_flag){
event->y[0] = SCREEN_MAX_Y - event->y[0];
}
if(1 == exchange_x_y_flag){
swap(event->x[0], event->y[0]);
}
}
#elif defined(TOUCH_KEY_FOR_EVB13)
if((event->x[0] > TOUCH_KEY_LOWER_X_LIMIT)&&(event->x[0]<TOUCH_KEY_HIGHER_X_LIMIT))
{
// printk("event->x=%d\n",event->x[0]);
if(1 == exchange_x_y_flag){
swap(event->x[0], event->y[0]);
}
// printk("event->x=%d,y=%d\n",event->x[0],event->y[0]);
if(0 == revert_x_flag){
event->x[0] = SCREEN_MAX_X - event->x[0];
}
if(1 == revert_y_flag){
event->y[0] = SCREEN_MAX_Y - event->y[0];
}
}
#else
if(1 == exchange_x_y_flag){
swap(event->x[0], event->y[0]);
}
//printk("event->x=%d,y=%d\n",event->x[0],event->y[0]);
if(0 == revert_x_flag){
event->x[0] = SCREEN_MAX_X - event->x[0];
}
if(1== revert_y_flag){
event->y[0] = SCREEN_MAX_Y - event->y[0];
}
//printk("x=%d\n",event->x[0]);
#endif
break;
default:
return -1;
}
#else
#endif
event->pressure = 200;
dev_dbg(&this_client->dev, "%s: 1:%d %d 2:%d %d \n", __func__,
event->x[0], event->y[0], event->x[1], event->y[1]);
return 0;
}
}
#ifdef TOUCH_KEY_LIGHT_SUPPORT
static void AW5306_lighting(void)
{
if(EGPIO_SUCCESS != gpio_write_one_pin_value(gpio_light_hdle, 1, "ctp_light")){
pr_info("AW5306_ts_light: err when operate gpio. \n");
}
msleep(15);
if(EGPIO_SUCCESS != gpio_write_one_pin_value(gpio_light_hdle, 0, "ctp_light")){
pr_info("AW5306_ts_light: err when operate gpio. \n");
}
return;
}
#endif
static void AW5306_report_multitouch(void)
{
struct AW5306_ts_data *data = i2c_get_clientdata(this_client);
struct ts_event *event = &data->event;
#ifdef TOUCH_KEY_SUPPORT
if(1 == key_tp){
return;
}
#endif
switch(event->touch_point) {
case 5:
input_report_abs(data->input_dev, ABS_MT_TRACKING_ID, event->touch_ID[4]);
input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR, event->pressure);
input_report_abs(data->input_dev, ABS_MT_POSITION_X, event->x[4]);
input_report_abs(data->input_dev, ABS_MT_POSITION_Y, event->y[4]);
input_report_abs(data->input_dev, ABS_MT_WIDTH_MAJOR, 1);
input_mt_sync(data->input_dev);
case 4:
input_report_abs(data->input_dev, ABS_MT_TRACKING_ID, event->touch_ID[3]);
input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR, event->pressure);
input_report_abs(data->input_dev, ABS_MT_POSITION_X, event->x[3]);
input_report_abs(data->input_dev, ABS_MT_POSITION_Y, event->y[3]);
input_report_abs(data->input_dev, ABS_MT_WIDTH_MAJOR, 1);
input_mt_sync(data->input_dev);
case 3:
input_report_abs(data->input_dev, ABS_MT_TRACKING_ID, event->touch_ID[2]);
input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR, event->pressure);
input_report_abs(data->input_dev, ABS_MT_POSITION_X, event->x[2]);
input_report_abs(data->input_dev, ABS_MT_POSITION_Y, event->y[2]);
input_report_abs(data->input_dev, ABS_MT_WIDTH_MAJOR, 1);
input_mt_sync(data->input_dev);
case 2:
input_report_abs(data->input_dev, ABS_MT_TRACKING_ID, event->touch_ID[1]);
input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR, event->pressure);
input_report_abs(data->input_dev, ABS_MT_POSITION_X, event->x[1]);
input_report_abs(data->input_dev, ABS_MT_POSITION_Y, event->y[1]);
input_report_abs(data->input_dev, ABS_MT_WIDTH_MAJOR, 1);
input_mt_sync(data->input_dev);
case 1:
input_report_abs(data->input_dev, ABS_MT_TRACKING_ID, event->touch_ID[0]);
input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR, event->pressure);
input_report_abs(data->input_dev, ABS_MT_POSITION_X, event->x[0]);
input_report_abs(data->input_dev, ABS_MT_POSITION_Y, event->y[0]);
input_report_abs(data->input_dev, ABS_MT_WIDTH_MAJOR, 1);
input_mt_sync(data->input_dev);
break;
default:
print_point_info("==touch_point default =\n");
break;
}
input_sync(data->input_dev);
dev_dbg(&this_client->dev, "%s: 1:%d %d 2:%d %d \n", __func__,
event->x[0], event->y[0], event->x[1], event->y[1]);
return;
}
#ifndef CONFIG_AW5306_MULTITOUCH
static void AW5306_report_singletouch(void)
{
struct AW5306_ts_data *data = i2c_get_clientdata(this_client);
struct ts_event *event = &data->event;
if (event->touch_point == 1) {
input_report_abs(data->input_dev, ABS_X, event->x1);
input_report_abs(data->input_dev, ABS_Y, event->y1);
input_report_abs(data->input_dev, ABS_PRESSURE, event->pressure);
}
input_report_key(data->input_dev, BTN_TOUCH, 1);
input_sync(data->input_dev);
dev_dbg(&this_client->dev, "%s: 1:%d %d 2:%d %d \n", __func__,
event->x1, event->y1, event->x2, event->y2);
return;
}
#endif
#ifdef TOUCH_KEY_SUPPORT
static void AW5306_report_touchkey(void)
{
struct AW5306_ts_data *data = i2c_get_clientdata(this_client);
struct ts_event *event = &data->event;
//printk("x=%d===Y=%d\n",event->x[0],event->y[0]);
#ifdef TOUCH_KEY_FOR_ANGDA
if((1==event->touch_point)&&(event->x1 > TOUCH_KEY_X_LIMIT)){
key_tp = 1;
if(event->x1 < 40){
key_val = 1;
input_report_key(data->input_dev, key_val, 1);
input_sync(data->input_dev);
print_point_info("===KEY 1====\n");
}else if(event->y1 < 90){
key_val = 2;
input_report_key(data->input_dev, key_val, 1);
input_sync(data->input_dev);
print_point_info("===KEY 2 ====\n");
}else{
key_val = 3;
input_report_key(data->input_dev, key_val, 1);
input_sync(data->input_dev);
print_point_info("===KEY 3====\n");
}
} else{
key_tp = 0;
}
#endif
#ifdef TOUCH_KEY_FOR_EVB13
if((1==event->touch_point)&&((event->y[0] > 510)&&(event->y[0]<530)))
{
if(key_tp != 1)
{
input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR, 0);
input_sync(data->input_dev);
}
else
{
//printk("===KEY touch ++++++++++====++=\n");
if(event->x[0] < 90){
key_val = 1;
input_report_key(data->input_dev, KEY_MENU, 1);
input_sync(data->input_dev);
// printk("===KEY 1===++=\n");
}else if((event->x[0] < 230)&&(event->x[0]>185)){
key_val = 2;
input_report_key(data->input_dev, KEY_BACK, 1);
input_sync(data->input_dev);
// printk("===KEY 2 ====\n");
}else if((event->x[0] < 355)&&(event->x[0]>305)){
key_val = 3;
input_report_key(data->input_dev, KEY_SEARCH, 1);
input_sync(data->input_dev);
// print_point_info("===KEY 3====\n");
}else if ((event->x[0] < 497)&&(event->x[0]>445)) {
key_val = 4;
input_report_key(data->input_dev, KEY_HOMEPAGE, 1);
input_sync(data->input_dev);
// print_point_info("===KEY 4====\n");
}else if ((event->x[0] < 615)&&(event->x[0]>570)) {
key_val = 5;
input_report_key(data->input_dev, KEY_VOLUMEDOWN, 1);
input_sync(data->input_dev);
// print_point_info("===KEY 5====\n");
}else if ((event->x[0] < 750)&&(event->x[0]>705)) {
key_val = 6;
input_report_key(data->input_dev, KEY_VOLUMEUP, 1);
input_sync(data->input_dev);
// print_point_info("===KEY 6====\n");
}
}
key_tp = 1;
}
else
{
key_tp = 0;
}
#endif
#ifdef TOUCH_KEY_LIGHT_SUPPORT
AW5306_lighting();
#endif
return;
}
#endif
static void AW5306_report_value(void)
{
#ifdef CONFIG_AW5306_MULTITOUCH
AW5306_report_multitouch();
#else /* CONFIG_AW5306_MULTITOUCH*/
AW5306_report_singletouch();
#endif /* CONFIG_AW5306_MULTITOUCH*/
#ifdef TOUCH_KEY_SUPPORT
AW5306_report_touchkey();
#endif
return;
} /*end AW5306_report_value*/
static void AW5306_ts_pen_irq_work(struct work_struct *work)
{
int ret = -1;
//printk("AW5306____read_data_test11111111\n");
if(suspend_flag != 1)
{
ret = AW5306_read_data();
//printk("AW5306_read_Data_ret = %d\n",ret);
if (ret == 0) {
AW5306_report_value();
}
}
else
{
AW5306_Sleep();
}
//enable_irq(SW_INT_IRQNO_PIO);
}
#ifdef INTMODE
static irqreturn_t AW5306_ts_interrupt(int irq, void *dev_id)
{
struct AW5306_ts_data *AW5306_ts = dev_id;
print_int_info("==========------AW5306_ts TS Interrupt-----============\n");
if(!ctp_ops.judge_int_occur()){
print_int_info("==IRQ_EINT21=\n");
ctp_ops.clear_penirq();
if (!work_pending(&AW5306_ts->pen_event_work))
{
print_int_info("Enter work\n");
queue_work(AW5306_ts->ts_workqueue, &AW5306_ts->pen_event_work);
}
}else{
print_int_info("Other Interrupt\n");
return IRQ_NONE;
}
return IRQ_HANDLED;
}
#else
void AW5306_tpd_polling(unsigned long data)
{
struct AW5306_ts_data *AW5306_ts = i2c_get_clientdata(this_client);
if (!work_pending(&AW5306_ts->pen_event_work)) {
queue_work(AW5306_ts->ts_workqueue, &AW5306_ts->pen_event_work);
}
if(suspend_flag != 1)
{
#ifdef AUTO_RUDUCEFRAME
if(tp_SlowMode)
{
AW5306_ts->touch_timer.expires = jiffies + HZ/AWTPCfg.SLOW_FRAME;
}
else
{
AW5306_ts->touch_timer.expires = jiffies + HZ/AWTPCfg.FAST_FRAME;
}
#else
AW5306_ts->touch_timer.expires = jiffies + HZ/AWTPCfg.FAST_FRAME;
#endif
add_timer(&AW5306_ts->touch_timer);
}
}
#endif
#ifdef CONFIG_HAS_EARLYSUSPEND
static void AW5306_ts_suspend(struct early_suspend *handler)
{
if(suspend_flag != 1)
{
printk("AW5306 SLEEP!!!");
suspend_flag = 1;
}
}
static void AW5306_ts_resume(struct early_suspend *handler)
{
struct AW5306_ts_data *AW5306_ts = i2c_get_clientdata(this_client);
if(suspend_flag != 0)
{
msleep(10);
//AW5306_TP_Reinit();
//AW5306_Sleep();
//AW_sleep(100);
//AW5306_TP_Init();
AW5306_User_Cfg1();
AW5306_TP_Reinit();
tp_idlecnt = 0;
tp_SlowMode = 0;
suspend_flag = 0;
printk("AW5306 WAKE UP!!!");
AW5306_read_data();
AW5306_report_value();
init_timer(&AW5306_ts->touch_timer);
AW5306_ts->touch_timer.expires = jiffies + HZ/AWTPCfg.FAST_FRAME;
add_timer(&AW5306_ts->touch_timer);
}
}
#endif //CONFIG_HAS_EARLYSUSPEND
static int
AW5306_ts_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
struct AW5306_ts_data *AW5306_ts;
struct input_dev *input_dev;
// struct device *dev;
// struct i2c_dev *i2c_dev;
int err = 0;
u8 reg_value;
#ifdef TOUCH_KEY_SUPPORT
int i = 0;
#endif
pr_info("====%s begin=====. \n", __func__);
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
err = -ENODEV;
goto exit_check_functionality_failed;
}
AW5306_ts = kzalloc(sizeof(*AW5306_ts), GFP_KERNEL);
if (!AW5306_ts) {
err = -ENOMEM;
goto exit_alloc_data_failed;
}
this_client = client;
#if 1
//pr_info("AW5306_ts_probe : client->addr = %d. \n", client->addr);
client->addr =0x38;
this_client->addr = client->addr;
printk("client addr2 = %x", client->addr);
reg_value = AW_I2C_ReadByte(0x01);
printk(" product id= %d", reg_value);
if(reg_value != 0xA8)
{
client->addr = 0x39;
//ft_ctp_reset();
ctp_wakeup(1,TS_WAKEUP_LOW_PERIOD);
dev_err(&client->dev, "AW5306_ts_probe: CHIP ID NOT CORRECT\n");
goto exit_check_functionality_failed;
}
#endif
i2c_set_clientdata(client, AW5306_ts);
#ifdef TOUCH_KEY_LIGHT_SUPPORT
gpio_light_hdle = gpio_request_ex("ctp_para", "ctp_light");
#endif
pr_info("==INIT_WORK=\n");
INIT_WORK(&AW5306_ts->pen_event_work, AW5306_ts_pen_irq_work);
AW5306_ts->ts_workqueue = create_singlethread_workqueue(dev_name(&client->dev));
if (!AW5306_ts->ts_workqueue) {
err = -ESRCH;
goto exit_create_singlethread;
}
input_dev = input_allocate_device();
if (!input_dev) {
err = -ENOMEM;
dev_err(&client->dev, "failed to allocate input device\n");
goto exit_input_dev_alloc_failed;
}
AW5306_ts->input_dev = input_dev;
#ifdef CONFIG_AW5306_MULTITOUCH
set_bit(ABS_MT_TOUCH_MAJOR, input_dev->absbit);
set_bit(ABS_MT_POSITION_X, input_dev->absbit);
set_bit(ABS_MT_POSITION_Y, input_dev->absbit);
set_bit(ABS_MT_WIDTH_MAJOR, input_dev->absbit);
#ifdef FOR_TSLIB_TEST
set_bit(BTN_TOUCH, input_dev->keybit);
set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
#endif
input_set_abs_params(input_dev,
ABS_MT_POSITION_X, 0, SCREEN_MAX_X, 0, 0);
input_set_abs_params(input_dev,
ABS_MT_POSITION_Y, 0, SCREEN_MAX_Y, 0, 0);
input_set_abs_params(input_dev,
ABS_MT_TOUCH_MAJOR, 0, PRESS_MAX, 0, 0);
input_set_abs_params(input_dev,
ABS_MT_WIDTH_MAJOR, 0, 200, 0, 0);
input_set_abs_params(input_dev,
ABS_MT_TRACKING_ID, 0, 4, 0, 0);
#ifdef TOUCH_KEY_SUPPORT
input_set_capability(input_dev,EV_KEY,KEY_BACK);
input_set_capability(input_dev,EV_KEY,KEY_MENU);
input_set_capability(input_dev,EV_KEY,KEY_HOMEPAGE);
input_set_capability(input_dev,EV_KEY,KEY_SEARCH);
input_set_capability(input_dev,EV_KEY,KEY_VOLUMEDOWN);
input_set_capability(input_dev,EV_KEY,KEY_VOLUMEUP);
set_bit(KEY_MENU, input_dev->keybit);
key_tp = 0;
input_dev->evbit[0] = BIT_MASK(EV_KEY);
for (i = 1; i < TOUCH_KEY_NUMBER; i++)
set_bit(i, input_dev->keybit);
#endif
#else
set_bit(ABS_X, input_dev->absbit);
set_bit(ABS_Y, input_dev->absbit);
set_bit(ABS_PRESSURE, input_dev->absbit);
set_bit(BTN_TOUCH, input_dev->keybit);
input_set_abs_params(input_dev, ABS_X, 0, SCREEN_MAX_X, 0, 0);
input_set_abs_params(input_dev, ABS_Y, 0, SCREEN_MAX_Y, 0, 0);
input_set_abs_params(input_dev,
ABS_PRESSURE, 0, PRESS_MAX, 0 , 0);
#endif
set_bit(EV_ABS, input_dev->evbit);
set_bit(EV_KEY, input_dev->evbit);
input_dev->name = CTP_NAME; //dev_name(&client->dev)
err = input_register_device(input_dev);
if (err) {
dev_err(&client->dev,
"AW5306_ts_probe: failed to register input device: %s\n",
dev_name(&client->dev));
goto exit_input_register_device_failed;
}
#ifdef CONFIG_HAS_EARLYSUSPEND
pr_info("==register_early_suspend =\n");
AW5306_ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
AW5306_ts->early_suspend.suspend = AW5306_ts_suspend;
AW5306_ts->early_suspend.resume = AW5306_ts_resume;
register_early_suspend(&AW5306_ts->early_suspend);
#endif
#ifdef CONFIG_AW5306_MULTITOUCH
pr_info("CONFIG_AW5306_MULTITOUCH is defined. \n");
#endif
#ifdef INTMODE
err = ctp_ops.set_irq_mode("ctp_para", "ctp_int_port", CTP_IRQ_MODE);
if(0 != err){
pr_info("%s:ctp_ops.set_irq_mode err. \n", __func__);
goto exit_set_irq_mode;
}
err = request_irq(SW_INT_IRQNO_PIO, AW5306_ts_interrupt, IRQF_TRIGGER_RISING | IRQF_SHARED, "AW5306_ts", AW5306_ts);
if (err < 0) {
dev_err(&client->dev, "AW5306_ts_probe: request irq failed\n");
goto exit_irq_request_failed;
}
#else
AW5306_create_sysfs(client);
AW5306_TP_Init();
AW5306_ts->touch_timer.function = AW5306_tpd_polling;
AW5306_ts->touch_timer.data = 0;
init_timer(&AW5306_ts->touch_timer);
AW5306_ts->touch_timer.expires = jiffies + HZ*5;
add_timer(&AW5306_ts->touch_timer);
#endif
// i2c_dev = get_free_i2c_dev(client->adapter);
/* if (IS_ERR(i2c_dev)){
err = PTR_ERR(i2c_dev);
return err;
}*/
/* dev = device_create(i2c_dev_class, &client->adapter->dev, MKDEV(I2C_MAJOR,client->adapter->nr), NULL, "aw_i2c_ts%d", client->adapter->nr);
if (IS_ERR(dev)) {
err = PTR_ERR(dev);
return err;
}
*/
pr_info("==%s over =\n", __func__);
return 0;
#ifdef INTMODE
exit_irq_request_failed:
exit_set_irq_mode:
#endif
cancel_work_sync(&AW5306_ts->pen_event_work);
destroy_workqueue(AW5306_ts->ts_workqueue);
//enable_irq(SW_INT_IRQNO_PIO);
exit_input_register_device_failed:
input_free_device(input_dev);
exit_input_dev_alloc_failed:
//free_irq(SW_INT_IRQNO_PIO, AW5306_ts);
exit_create_singlethread:
pr_info("==singlethread error =\n");
i2c_set_clientdata(client, NULL);
kfree(AW5306_ts);
exit_alloc_data_failed:
exit_check_functionality_failed:
return err;
}
static int __devexit AW5306_ts_remove(struct i2c_client *client)
{
struct AW5306_ts_data *AW5306_ts = i2c_get_clientdata(client);
pr_info("==AW5306_ts_remove=\n");
#ifdef INTMODE
free_irq(SW_INT_IRQNO_PIO, AW5306_ts);
#else
del_timer(&AW5306_ts->touch_timer);
#endif
#ifdef CONFIG_HAS_EARLYSUSPEND
unregister_early_suspend(&AW5306_ts->early_suspend);
#endif
input_unregister_device(AW5306_ts->input_dev);
input_free_device(AW5306_ts->input_dev);
cancel_work_sync(&AW5306_ts->pen_event_work);
destroy_workqueue(AW5306_ts->ts_workqueue);
kfree(AW5306_ts);
i2c_set_clientdata(client, NULL);
//lkj ctp_ops.free_platform_resource();
return 0;
}
static const struct i2c_device_id AW5306_ts_id[] = {
{ CTP_NAME, 0 },
{}
};
MODULE_DEVICE_TABLE(i2c, AW5306_ts_id);
static struct i2c_driver AW5306_ts_driver = {
.class = I2C_CLASS_HWMON,
.probe = AW5306_ts_probe,
.remove = __devexit_p(AW5306_ts_remove),
.id_table = AW5306_ts_id,
.driver = {
.name = CTP_NAME,
.owner = THIS_MODULE,
},
.address_list = normal_i2c,
};
static int __init AW5306_ts_init(void)
{
int ret = -1;
// int err = -1;
//lkj =====begin============
printk("AW5306_ts_init:****************************************************************\n");
if (input_fetch_sysconfig_para(&(config_info.input_type))){
printk("%s: ctp_fetch_sysconfig_para err.\n", __func__);
return 0;
}else{
ret = input_init_platform_resource(&(config_info.input_type));
if (0 != ret) {
printk("%s:ctp_ops.init_platform_resource err. \n", __func__);
}
}
if(config_info.ctp_used == 0){
printk("*** ctp_used set to 0 !\n");
printk("*** if use ctp,please put the sys_config.fex ctp_used set to 1. \n");
return 0;
}
if(!ctp_get_system_config()){
printk("%s:read config fail!\n", __func__);
return ret;
}
ctp_wakeup(1,TS_WAKEUP_LOW_PERIOD);
AW5306_ts_driver.detect = ctp_detect;
//==================end===================
#if 0
pr_info("===========================%s=====================\n", __func__);
if (ctp_ops.fetch_sysconfig_para)
{
if(ctp_ops.fetch_sysconfig_para()){
pr_info("%s: err.\n", __func__);
return -1;
}
}
pr_info("%s: after fetch_sysconfig_para: normal_i2c: 0x%hx. normal_i2c[1]: 0x%hx \n", \
__func__, u_i2c_addr.normal_i2c[0], u_i2c_addr.normal_i2c[1]);
err = ctp_ops.init_platform_resource();
if(0 != err){
pr_info("%s:ctp_ops.init_platform_resource err. \n", __func__);
}
//reset
ctp_ops.ts_reset();
//wakeup
ctp_ops.ts_wakeup();
AW5306_ts_driver.detect = ctp_ops.ts_detect;
/* if(ret) {
pr_info(KERN_ERR "%s:register chrdev failed\n",__FILE__);
return ret;
}
*/
#endif
i2c_dev_class = class_create(THIS_MODULE,"aw_i2c_dev");
if (IS_ERR(i2c_dev_class)) {
ret = PTR_ERR(i2c_dev_class);
class_destroy(i2c_dev_class);
}
ret = i2c_add_driver(&AW5306_ts_driver);
return ret;
}
static void __exit AW5306_ts_exit(void)
{
pr_info("==AW5306_ts_exit==\n");
i2c_del_driver(&AW5306_ts_driver);
input_free_platform_resource(&(config_info.input_type));
}
late_initcall(AW5306_ts_init);
module_exit(AW5306_ts_exit);
MODULE_AUTHOR("<whj@AWINIC.com>");
MODULE_DESCRIPTION("AWINIC AW5306 TouchScreen driver");
MODULE_LICENSE("GPL");