#include <linux/async.h>
#include <mach/gpio.h>
#include <mach/board.h>
+#include <linux/earlysuspend.h>
+#include <linux/input/mt.h>
+
+struct FTS_TS_DATA_T {
+ struct i2c_client *client;
+ struct input_dev *input_dev;
+ struct FTS_TS_EVENT_T event;
+ struct work_struct pen_event_work;
+ struct workqueue_struct *ts_workqueue;
+ struct early_suspend early_suspend;
+};
+
/* -------------- global variable definition -----------*/
static struct i2c_client *this_client;
static REPORT_FINGER_INFO_T _st_finger_infos[CFG_MAX_POINT_NUM];
static bool tsp_keystatus[CFG_NUMOFKEYS];
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void ft5x0x_ts_early_suspend(struct early_suspend *h);
+static void ft5x0x_ts_late_resume(struct early_suspend *h);
+#endif
+
+
/***********************************************************************
[function]:
callback: read data from ctpm by i2c interface;
if ( _st_finger_infos[i].u2_pressure == -1 )
continue;
- _st_finger_infos[i].u2_pressure = 0;
+ input_mt_slot(data->input_dev, i);
+ input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER, false);
- input_report_abs(data->input_dev, ABS_MT_POSITION_X, SCREEN_MAX_X - _st_finger_infos[i].i2_x);
+/*
+ input_report_abs(data->input_dev, ABS_MT_POSITION_X, _st_finger_infos[i].i2_x);
input_report_abs(data->input_dev, ABS_MT_POSITION_Y, _st_finger_infos[i].i2_y);
input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR, _st_finger_infos[i].u2_pressure);
input_report_abs(data->input_dev, ABS_MT_TRACKING_ID, _st_finger_infos[i].ui2_id);
input_mt_sync(data->input_dev);
-
+*/
i_need_sync = 1;
if ( _st_finger_infos[i].u2_pressure == 0 )
msg.flags = 0;
msg.len = 1;
msg.buf = rxdata;
+ msg.scl_rate = FT5X0X_I2C_SPEED;
+
ret = i2c_transfer(this_client->adapter, &msg, 1);
- if (ret < 0)
- pr_err("msg %s i2c write error: %d\n", __func__, ret);
-
+ if(ret == 0){
+ pr_err("msg %s line:%d i2c write error: %d\n", __func__, __LINE__,ret);
+ return -EBUSY;
+ }else if(ret < 0){
+ pr_err("msg %s line:%d i2c write error: %d\n", __func__, __LINE__,ret);
+ return ret;
+ }
+
msg.addr = this_client->addr;
msg.flags = I2C_M_RD;
msg.len = length;
msg.buf = rxdata;
+ msg.scl_rate = FT5X0X_I2C_SPEED;
ret = i2c_transfer(this_client->adapter, &msg, 1);
- if (ret < 0)
- pr_err("msg %s i2c write error: %d\n", __func__, ret);
+
+ if(ret == 0){
+ pr_err("msg %s line:%d i2c write error: %d\n", __func__, __LINE__,ret);
+ return -EBUSY;
+ }else if(ret < 0){
+ pr_err("msg %s line:%d i2c write error: %d\n", __func__, __LINE__,ret);
+ return ret;
+ }
return ret;
}
msg.flags = 0;
msg.len = length;
msg.buf = txdata;
+ msg.scl_rate = FT5X0X_I2C_SPEED;
+
ret = i2c_transfer(this_client->adapter, &msg, 1);
- if (ret < 0)
- pr_err("%s i2c write error: %d\n", __func__, ret);
+
+ if(ret == 0){
+ pr_err("msg %s line:%d i2c write error: %d\n", __func__, __LINE__,ret);
+ return -EBUSY;
+ }else if(ret < 0){
+ pr_err("msg %s line:%d i2c write error: %d\n", __func__, __LINE__,ret);
+ return ret;
+ }
return ret;
}
int fts_read_data(void)
{
struct FTS_TS_DATA_T *data = i2c_get_clientdata(this_client);
- struct FTS_TS_EVENT_T *event = &data->event;
u8 buf[32] = {0};
- static int key_id=0x80;
+// static int key_id=0x80;
- int i,id,temp,i_count,ret = -1;
- int touch_point_num = 0, touch_event, x, y, pressure, size;
- REPORT_FINGER_INFO_T touch_info[CFG_MAX_POINT_NUM];
+ int id,i_count,ret = -1;
+ int touch_point_num = 0, touch_event, x, y;
+ int tmp, swap ,sync_flag = 0;
+ buf[0] = 2;//ADDR
+ ret = fts_i2c_rxdata(buf, 1);
+ if (ret > 0)
+ touch_point_num = buf[0]&0xf;
+ else
+ printk(KERN_ERR "get fingers failed!\n");
+// printk(KERN_INFO "touch_point_num=%d\n", touch_point_num);
+ if(touch_point_num > CFG_MAX_POINT_NUM)
+ printk("[Warning],+++++Touch number[%d] readed is larger than max point number+++++++++++++\n",touch_point_num);
+
i_count = 0;
- do
+ if(touch_point_num != 0)
{
- buf[0] = 3;
-
- id = 0xe;
-
- ret=fts_i2c_rxdata(buf, 6);
- if (ret > 0)
+ buf[0] = 3;//ADDR
+ ret=fts_i2c_rxdata(buf, 6*touch_point_num);
+ if(ret >= 0)
{
-
- id = buf[2]>>4;
- //printk("\n--the id number is %d---\n",id);
- touch_event = buf[0]>>6;
- if (id >= 0 && id< CFG_MAX_POINT_NUM)
+ do
{
-
- temp = buf[0]& 0x0f;
- temp = temp<<8;
- temp = temp | buf[1];
- x = temp;
-
- temp = (buf[2])& 0x0f;
- temp = temp<<8;
- temp = temp | buf[3];
- y=temp;
-
- {
- int swap;
+ id = buf[2+i_count*6]>>4;
+ if(id <0 || id>CFG_MAX_POINT_NUM)
+ printk("[ERROR] Touch ID readed is illegal!!\n");
- //x = (768-x)*600/768;
- //y = y*1024/1024;
-
- swap = x;
- x = y;
- y = swap;
-
- //x = 1024 - x;////////////////////////////
- y = 600 - y;
+ touch_event = buf[i_count*6]>>6;
+ x =((buf[i_count*6]& 0x0f)<<8) |buf[i_count*6+1];
+ y =( (buf[i_count*6+2]& 0x0f)<<8) | buf[i_count*6+3];
+
+ //adjust value
+ x = 600 - x;
+ y = 1024 - y;
+#if 1
+ {//swap
+ swap = x;
+ x = y;
+ y = swap;
}
-
-
- pressure = buf[4] & 0x3f;
- size = buf[5]&0xf0;
- size = (id<<8)|size;
- touch_event = buf[0]>>6;
-
- if (touch_event == 0) //press down
- {
- //if(y>=0 && y<850)
- {
-
-
- _st_finger_infos[id].u2_pressure= 1;//pressure;
- _st_finger_infos[id].i2_x= (int16_t)x;
- _st_finger_infos[id].i2_y= (int16_t)y;
- _st_finger_infos[id].ui2_id = size;
- _si_touch_num ++;
-// printk("\n--report x position is %d,pressure=%d----\n",_st_finger_infos[id].i2_x, pressure);
-// printk("\n--report y position is %d,pressure=%d----\n",_st_finger_infos[id].i2_y, pressure);
- }
-#if 0
-
- else if(y>=850 && y<=860)
- {
- if (x>=75 && x<=90)
- {
- key_id = 0;
- printk("\n---virtual key 1 press---");
- }
- else if ( x>=185 && x<=200)
- {
- key_id = 1;
- printk("\n---virtual key 2 press---");
- }
- else if (x>=290 && x<=305)
- {
- key_id = 2;
- printk("\n---virtual key 3 press---");
- }
- else if ( x>=405 && x<=420)
- {
- key_id = 3;
- printk("\n---virtual key 4 press---");
- }
-
-
- input_report_key(data->input_dev, tsp_keycodes[key_id], 1);
- tsp_keystatus[key_id] = KEY_PRESS;
-
- }
#endif
- }
-
+ if (touch_event == 0) //down
+ {
+ _st_finger_infos[i_count].u2_pressure= 1;//pressure;
+ _st_finger_infos[i_count].i2_x= (int16_t)x;
+ _st_finger_infos[i_count].i2_y= (int16_t)y;
+ }
else if (touch_event == 1) //up event
{
-
- _st_finger_infos[id].u2_pressure= 0;
-#if 0
- if(key_id !=0x80)
- {
- i=key_id;
- printk("\n");
- printk("\n---virtual key %d release---\n",++i);
- for(i=0;i<8;i++)
- input_report_key(data->input_dev, tsp_keycodes[key_id], 0);
-
- key_id=0x80;
- }
-#endif
+ _st_finger_infos[i_count].u2_pressure= 0;
}
-
else if (touch_event == 2) //move
{
-// printk("[TSP]id=%d move\n", id);
- _st_finger_infos[id].u2_pressure= 1;//pressure;
- _st_finger_infos[id].i2_x= (int16_t)x;
- _st_finger_infos[id].i2_y= (int16_t)y;
- _st_finger_infos[id].ui2_id = size;
- _si_touch_num ++;
+ _st_finger_infos[i_count].u2_pressure= 1;//pressure;
+ _st_finger_infos[i_count].i2_x= (int16_t)x;
+ _st_finger_infos[i_count].i2_y= (int16_t)y;
}
- else
- /*bad event, ignore*/
+ else /*bad event, ignore*/
+ {
+ printk("Bad event, ignore!!!\n");
+ i_count++;
continue;
-
-
- if ( (touch_event==1) )
+ }
+
+ if(_st_finger_infos[i_count].u2_pressure == 1)//down
{
-// printk("[TSP]id=%d up\n", id);
+ input_mt_slot(data->input_dev, id);
+ input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER, true);
+ input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR, 1);
+ input_report_abs(data->input_dev, ABS_MT_POSITION_X, _st_finger_infos[i_count].i2_x);
+ input_report_abs(data->input_dev, ABS_MT_POSITION_Y, _st_finger_infos[i_count].i2_y);
+ sync_flag = 1;
}
-
-
- for( i= 0; i<CFG_MAX_POINT_NUM; ++i )
+ else if(_st_finger_infos[i_count].u2_pressure == 0)//up
{
-
- input_report_abs(data->input_dev, ABS_MT_TRACKING_ID, _st_finger_infos[i].ui2_id);
- input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR, _st_finger_infos[i].u2_pressure);
- input_report_abs(data->input_dev, ABS_MT_POSITION_X, SCREEN_MAX_X - _st_finger_infos[i].i2_x);
- input_report_abs(data->input_dev, ABS_MT_POSITION_Y, _st_finger_infos[i].i2_y);
- input_mt_sync(data->input_dev);
-
- if(_st_finger_infos[i].u2_pressure == 0 )
- {
- _st_finger_infos[i].u2_pressure= -1;
- }
-
+ input_mt_slot(data->input_dev, id);
+ input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER, false);
+ sync_flag = 1;
}
+
- input_sync(data->input_dev);
-
- if (_si_touch_num == 0 )
+ if(_st_finger_infos[i_count].u2_pressure == 0 )
{
- fts_ts_release();
+ _st_finger_infos[i_count].u2_pressure= -1;
}
- _si_touch_num = 0;
- }
+
+ input_sync(data->input_dev);
- }
+ i_count++;
+ }while(i_count < touch_point_num);
+
+ if(sync_flag)
+ input_sync(data->input_dev);
+ }
else
{
- printk("[TSP] ERROR: in %s, line %d, ret = %d\n",
+ printk("[LAIBAO] ERROR: in %s, line %d, ret = %d\n",
__FUNCTION__, __LINE__, ret);
}
-
- i_count ++;
- }while( id != 0xf && i_count < 12);
-
- event->touch_point = touch_point_num;
- if (event->touch_point == 0)
- return 1;
-
- switch (event->touch_point) {
- case 5:
- event->x5 = touch_info[4].i2_x;
- event->y5 = touch_info[4].i2_y;
- event->pressure5 = touch_info[4].u2_pressure;
- case 4:
- event->x4 = touch_info[3].i2_x;
- event->y4 = touch_info[3].i2_y;
- event->pressure4= touch_info[3].u2_pressure;
- case 3:
- event->x3 = touch_info[2].i2_x;
- event->y3 = touch_info[2].i2_y;
- event->pressure3= touch_info[2].u2_pressure;
- case 2:
- event->x2 = touch_info[1].i2_x;
- event->y2 = touch_info[1].i2_y;
- event->pressure2= touch_info[1].u2_pressure;
- case 1:
- event->x1 = touch_info[0].i2_x;
- event->y1 = touch_info[0].i2_y;
- event->pressure1= touch_info[0].u2_pressure;
- break;
- default:
- return -1;
}
+ //If touch number is zero then release touch.
+ if(touch_point_num == 0 )
+ {
+ fts_ts_release();
+ }
+
return 0;
}
}
+void ft5x0x_ts_set_standby(struct i2c_client *client, int enable)
+{
+ struct laibao_platform_data *mach_info = client->dev.platform_data;
+ unsigned pwr_pin = mach_info->pwr_pin;
+ unsigned pwr_on_value = mach_info->pwr_on_value;
+ unsigned reset_pin = mach_info->reset_pin;
+ unsigned reset_value = mach_info->reset_value;
+
+ printk("%s : %s, enable = %d\n", __FILE__, __FUNCTION__,enable);
+ if(pwr_pin != INVALID_GPIO)
+ {
+ gpio_direction_output(pwr_pin, 0);
+ gpio_set_value(pwr_pin, enable ? pwr_on_value : !pwr_on_value);
+ }
+ if(reset_pin != INVALID_GPIO)
+ {
+ gpio_direction_output(reset_pin, enable ? reset_value : !reset_value);
+ gpio_set_value(reset_pin, enable ? reset_value : !reset_value);
+ }
+}
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void ft5x0x_ts_early_suspend(struct early_suspend *h)
+{
+ struct FTS_TS_DATA_T *data = i2c_get_clientdata(this_client);
+
+
+ printk("enter ft5x0x_ts_early_suspend\n");
+
+ cancel_work_sync(&data->pen_event_work);
+
+ disable_irq(this_client->irq);
+
+
+ ft5x0x_ts_set_standby(this_client,0);
+
+ return;
+}
+static void ft5x0x_ts_late_resume(struct early_suspend *h)
+{
+ struct FTS_TS_DATA_T *data = i2c_get_clientdata(this_client);
+
+ ft5x0x_ts_set_standby(this_client,1);
+
+ enable_irq(this_client->irq);
+
+ printk("ft5x0x_ts_late_resume finish\n");
+
+ return ;
+}
+#else
+#define ft5x0x_ts_early_suspend NULL
+#define ft5x0x_ts_late_resume NULL
+#endif
+
static int fts_ts_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
struct laibao_platform_data *pdata = client->dev.platform_data;
- client->irq = gpio_to_irq(client->irq);
- _sui_irq_num = client->irq;
+ printk("[LAIBAO] file(%s), function (%s), --probe start\n", __FILE__, __FUNCTION__);
- printk("[TSP] file(%s), function (%s), --probe start\n", __FILE__, __FUNCTION__);
-
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
err = -ENODEV;
goto exit_check_functionality_failed;
}
+ if (pdata->init_platform_hw) {
+ err = pdata->init_platform_hw();
+ if (err < 0) {
+ printk("[LAIBAO] init_platform_hw failed\n");
+ goto exit_init_platform_hw_failed;
+ }
+ }
+
+ msleep(200);
+
+ this_client = client;
+ err = i2c_master_reg8_recv(this_client, FT5X0X_REG_FIRMID, ®_version, 1, 200*1000);
+ if (err < 0) {
+ printk("[LAIBAO] Device not found\n");
+ goto exit_device_not_found;
+ }
+
+ client->irq = gpio_to_irq(client->irq);
+ _sui_irq_num = client->irq;
+
ft5x0x_ts = kzalloc(sizeof(*ft5x0x_ts), GFP_KERNEL);
if (!ft5x0x_ts) {
err = -ENOMEM;
goto exit_alloc_data_failed;
}
- this_client = client;
+ //this_client = client;
+ ft5x0x_ts->client = client;
i2c_set_clientdata(client, ft5x0x_ts);
INIT_WORK(&ft5x0x_ts->pen_event_work, fts_work_func);
goto exit_create_singlethread;
}
- if (pdata->init_platform_hw)
- pdata->init_platform_hw();
-
-
-
/***wait CTP to bootup normally***/
- msleep(200);
+ //msleep(200);
//fts_register_read(FT5X0X_REG_FIRMID, ®_version,1);
i2c_master_reg8_recv(this_client, FT5X0X_REG_FIRMID, ®_version, 1, 200*1000);
- printk("[TSP] firmware version = 0x%2x\n", reg_version);
+ printk("[LAIBAO] firmware version = 0x%2x\n", reg_version);
//fts_register_read(FT5X0X_REG_REPORT_RATE, ®_value,1);
i2c_master_reg8_recv(this_client, FT5X0X_REG_REPORT_RATE, ®_value, 1, 200*1000);
- printk("[TSP]firmware report rate = %dHz\n", reg_value*10);
+ printk("[LAIBAO] firmware report rate = %dHz\n", reg_value*10);
//fts_register_read(FT5X0X_REG_THRES, ®_value,1);
i2c_master_reg8_recv(this_client, FT5X0X_REG_THRES, ®_value, 1, 200*1000);
- printk("[TSP]firmware threshold = %d\n", reg_value * 4);
+ printk("[LAIBAO] firmware threshold = %d\n", reg_value * 4);
//fts_register_read(FT5X0X_REG_NOISE_MODE, ®_value,1);
i2c_master_reg8_recv(this_client, FT5X0X_REG_NOISE_MODE, ®_value, 1, 200*1000);
- printk("[TSP]nosie mode = 0x%2x\n", reg_value);
+ printk("[LAIBAO] nosie mode = 0x%2x\n", reg_value);
#if 0
if (fts_ctpm_get_upg_ver() != reg_version)
{
- printk("[TSP] start upgrade new verison 0x%2x\n", fts_ctpm_get_upg_ver());
+ printk("[LAIBAO] start upgrade new verison 0x%2x\n", fts_ctpm_get_upg_ver());
msleep(200);
err = fts_ctpm_fw_upgrade_with_i_file();
if (err == 0)
{
- printk("[TSP] ugrade successfuly.\n");
+ printk("[LAIBAO] ugrade successfuly.\n");
msleep(300);
fts_register_read(FT5X0X_REG_FIRMID, ®_value,1);
printk("FTS_DBG from old version 0x%2x to new version = 0x%2x\n", reg_version, reg_value);
}
else
{
- printk("[TSP] ugrade fail err=%d, line = %d.\n",
+ printk("[LAIBAO] ugrade fail err=%d, line = %d.\n",
err, __LINE__);
}
msleep(4000);
}
#endif
- printk("[TSP]=========================_sui_irq_num = %d ================\n",_sui_irq_num);
- printk("[TSP]=========================client->dev.driver->name = %s ================\n",client->dev.driver->name);
+ printk("[LAIBAO]=========================_sui_irq_num = %d ================\n",_sui_irq_num);
+ printk("[LAIBAO]=========================client->dev.driver->name = %s ================\n",client->dev.driver->name);
err = request_irq(_sui_irq_num, fts_ts_irq, GPIOEdgelFalling, client->dev.driver->name, ft5x0x_ts);
if (err < 0) {
- dev_err(&client->dev, "[TSP]ft5x0x_probe: request irq failed\n");
- printk("[TSP]=========================err = %d ================\n",err);
+ dev_err(&client->dev, "[LAIBAO] ft5x0x_probe: request irq failed\n");
+ printk("[LAIBAO]=========================err = %d ================\n",err);
goto exit_irq_request_failed;
}
disable_irq(_sui_irq_num);
-
+
+
input_dev = input_allocate_device();
if (!input_dev) {
err = -ENOMEM;
- dev_err(&client->dev, "[TSP]failed to allocate input device\n");
+ dev_err(&client->dev, "[LAIBAO]failed to allocate input device\n");
goto exit_input_dev_alloc_failed;
}
//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);
- input_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+
+// input_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+
+ __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+ __set_bit(EV_ABS, input_dev->evbit);
/****** for multi-touch *******/
for (i=0; i<CFG_MAX_POINT_NUM; i++)
_st_finger_infos[i].u2_pressure = -1;
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);
+ ABS_MT_POSITION_X, 0, SCREEN_MAX_X + SCREEN_BOUNDARY_ADJUST_VALUE, 0, 0);
input_set_abs_params(input_dev,
- ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
+ ABS_MT_POSITION_Y, 0, SCREEN_MAX_Y + SCREEN_BOUNDARY_ADJUST_VALUE, 0, 0);
+// input_set_abs_params(input_dev,
+// ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
//input_set_abs_params(input_dev,
// ABS_MT_TRACKING_ID, 0, 30, 0, 0);
- input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0);
+// input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0);
+
+ input_mt_init_slots(input_dev, CFG_MAX_POINT_NUM);
+ input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
+
/*****setup key code area******/
//set_bit(EV_SYN, input_dev->evbit);
//set_bit(EV_KEY, input_dev->evbit);
goto exit_input_register_device_failed;
}
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ ft5x0x_ts->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB + 1;
+ ft5x0x_ts->early_suspend.suspend = ft5x0x_ts_early_suspend;
+ ft5x0x_ts->early_suspend.resume = ft5x0x_ts_late_resume;
+ register_early_suspend(&ft5x0x_ts->early_suspend);
+#endif
+
+
enable_irq(_sui_irq_num);
- printk("[TSP] file(%s), function (%s), -- end\n", __FILE__, __FUNCTION__);
+ printk("[LAIBAO] file(%s), function (%s), -- end\n", __FILE__, __FUNCTION__);
return 0;
exit_input_register_device_failed:
cancel_work_sync(&ft5x0x_ts->pen_event_work);
destroy_workqueue(ft5x0x_ts->ts_workqueue);
exit_create_singlethread:
- printk("[TSP] ==singlethread error =\n");
i2c_set_clientdata(client, NULL);
kfree(ft5x0x_ts);
exit_alloc_data_failed:
+exit_device_not_found:
+ if (pdata->exit_platform_hw)
+ pdata->exit_platform_hw();
+
+exit_init_platform_hw_failed:
exit_check_functionality_failed:
return err;
}