From 1bf5fe9a2f55bbe0cbb86189040a6d2cb5bea3a5 Mon Sep 17 00:00:00 2001 From: zwp Date: Tue, 9 Aug 2011 06:41:41 -0700 Subject: [PATCH] phone-pad:add laibao touch screen driver,and add mpu3050 support --- arch/arm/configs/rk29_phonepadsdk_defconfig | 29 +- arch/arm/mach-rk29/board-rk29phonepadsdk.c | 152 ++- arch/arm/mach-rk29/include/mach/board.h | 10 + drivers/input/touchscreen/Kconfig | 6 + drivers/input/touchscreen/Makefile | 1 + drivers/input/touchscreen/ft5x0x_i2c_ts.c | 1024 +++++++++++++++++++ drivers/input/touchscreen/ft5x0x_i2c_ts.h | 121 +++ 7 files changed, 1333 insertions(+), 10 deletions(-) mode change 100755 => 100644 arch/arm/mach-rk29/board-rk29phonepadsdk.c mode change 100755 => 100644 arch/arm/mach-rk29/include/mach/board.h mode change 100755 => 100644 drivers/input/touchscreen/Kconfig create mode 100644 drivers/input/touchscreen/ft5x0x_i2c_ts.c create mode 100644 drivers/input/touchscreen/ft5x0x_i2c_ts.h diff --git a/arch/arm/configs/rk29_phonepadsdk_defconfig b/arch/arm/configs/rk29_phonepadsdk_defconfig index cafb2b439fb1..09c7fb3c32ce 100644 --- a/arch/arm/configs/rk29_phonepadsdk_defconfig +++ b/arch/arm/configs/rk29_phonepadsdk_defconfig @@ -839,8 +839,33 @@ CONFIG_MODEM_ROCKCHIP_DEMO=y # Motion Sensors Support # # CONFIG_MPU_NONE is not set -# CONFIG_SENSORS_MPU3050 is not set -# CONFIG_SENSORS_MPU6000 is not set +CONFIG_MPU_SENSORS_MPU3050=y +# CONFIG_MPU_SENSORS_MPU6000 is not set +# CONFIG_MPU_SENSORS_ACCELEROMETER_NONE is not set +# CONFIG_MPU_SENSORS_ADXL346 is not set +# CONFIG_MPU_SENSORS_BMA150 is not set +# CONFIG_MPU_SENSORS_BMA222 is not set +# CONFIG_MPU_SENSORS_KXSD9 is not set +CONFIG_MPU_SENSORS_KXTF9=y +# CONFIG_MPU_SENSORS_LIS331DLH is not set +# CONFIG_MPU_SENSORS_LIS3DH is not set +# CONFIG_MPU_SENSORS_LSM303DLHA is not set +# CONFIG_MPU_SENSORS_MMA8450 is not set +# CONFIG_MPU_SENSORS_MMA845X is not set +CONFIG_MPU_SENSORS_COMPASS_NONE=y +# CONFIG_MPU_SENSORS_AK8975 is not set +# CONFIG_MPU_SENSORS_MMC314X is not set +# CONFIG_MPU_SENSORS_AMI30X is not set +# CONFIG_MPU_SENSORS_AMI306 is not set +# CONFIG_MPU_SENSORS_HMC5883 is not set +# CONFIG_MPU_SENSORS_LSM303DLHM is not set +# CONFIG_MPU_SENSORS_YAS529 is not set +# CONFIG_MPU_SENSORS_YAS530 is not set +# CONFIG_MPU_SENSORS_HSCDTD002B is not set +# CONFIG_MPU_SENSORS_HSCDTD004A is not set +CONFIG_MPU_SENSORS_PRESSURE_NONE=y +# CONFIG_MPU_SENSORS_BMA085 is not set +CONFIG_MPU_SENSORS_TIMERIRQ=y CONFIG_HAVE_IDE=y # CONFIG_IDE is not set diff --git a/arch/arm/mach-rk29/board-rk29phonepadsdk.c b/arch/arm/mach-rk29/board-rk29phonepadsdk.c old mode 100755 new mode 100644 index e1c21f3c836b..10e64919aaf5 --- a/arch/arm/mach-rk29/board-rk29phonepadsdk.c +++ b/arch/arm/mach-rk29/board-rk29phonepadsdk.c @@ -60,6 +60,7 @@ #include +#include #ifdef CONFIG_VIDEO_RK29 /*---------------- Camera Sensor Macro Define Begin ------------------------*/ /*---------------- Camera Sensor Configuration Macro Begin ------------------------*/ @@ -538,6 +539,69 @@ struct nas_platform_data nas_info = { }; #endif +#if defined (CONFIG_LAIBAO_TS) +#define TOUCH_RESET_PIN RK29_PIN4_PD5//RK29_PIN6_PC3 +#define TOUCH_INT_PIN RK29_PIN0_PA2 +void laibao_reset(void) +{ + msleep(5); + gpio_pull_updown(TOUCH_INT_PIN, 1); + gpio_direction_output(TOUCH_RESET_PIN, 0); + msleep(5); + gpio_set_value(TOUCH_RESET_PIN,GPIO_LOW); + msleep(200); + gpio_set_value(TOUCH_RESET_PIN,GPIO_HIGH); +} +void laibao_hold(void) +{ + printk("nas_hold()\n"); + gpio_direction_output(TOUCH_RESET_PIN, 0); + msleep(5); + gpio_set_value(TOUCH_RESET_PIN,GPIO_LOW); + msleep(30); + } +void laibao_request_io(void) +{ + if(gpio_request(TOUCH_RESET_PIN,NULL) != 0){ + gpio_free(TOUCH_RESET_PIN); + printk("nas_init_platform_hw gpio_request error\n"); + return -EIO; + } + + if(gpio_request(TOUCH_INT_PIN,NULL) != 0){ + gpio_free(TOUCH_INT_PIN); + printk("nas_init_platform_hw gpio_request error\n"); + return -EIO; + } +} + +int laibao_init_platform_hw(void) +{ + printk("enter %s()\n", __FUNCTION__); + laibao_request_io(); + laibao_reset(); + + if(gpio_request(RK29_PIN6_PD3,NULL) != 0){ + gpio_free(RK29_PIN6_PD3); + printk("mma8452_init_platform_hw gpio_request error\n"); + return -EIO; + } + + gpio_direction_output(RK29_PIN6_PD3, 0); + gpio_set_value(TOUCH_RESET_PIN,GPIO_HIGH); + + + return 0; +} + + +struct laibao_platform_data laibao_info = { + .model= 1003, + .init_platform_hw= laibao_init_platform_hw, + +}; +#endif + #if defined (CONFIG_D70_L3188A) struct goodix_i2c_rmi_platform_data d70_l3188a_info = { @@ -571,6 +635,57 @@ static struct mma8452_platform_data mma8452_info = { }; #endif +#if defined (CONFIG_MPU_SENSORS_MPU3050) +/*mpu3050*/ +static struct mpu3050_platform_data mpu3050_data = { + .int_config = 0x10, + //.orientation = { 1, 0, 0,0, -1, 0,0, 0, 1 }, + //.orientation = { 0, 1, 0,-1, 0, 0,0, 0, -1 }, + //.orientation = { -1, 0, 0,0, -1, 0,0, 0, -1 }, + .orientation = { 1, 0, 0, 0, 1, 0, 0, 0, -1 }, + .level_shifter = 0, +#if defined (CONFIG_MPU_SENSORS_KXTF9) + .accel = { +#ifdef CONFIG_MPU_SENSORS_MPU3050_MODULE + .get_slave_descr = NULL , +#else + .get_slave_descr = get_accel_slave_descr , +#endif + .adapt_num = 0, // The i2c bus to which the mpu device is + // connected + .irq = RK29_PIN0_PA3, + .bus = EXT_SLAVE_BUS_SECONDARY, //The secondary I2C of MPU + .address = 0x0f, + //.orientation = { 1, 0, 0,0, 1, 0,0, 0, 1 }, + //.orientation = { 0, -1, 0,-1, 0, 0,0, 0, -1 }, + //.orientation = { 0, 1, 0,1, 0, 0,0, 0, -1 }, + + .orientation = { 1, 0, 0, 0, -1, 0, 0, 0, -1 }, + //.orientation = { 0, 1, 0, -1, 0, 0, 0, 0, -1 }, + }, +#endif +#if defined (CONFIG_MPU_SENSORS_AK8975) + .compass = { +#ifdef CONFIG_MPU_SENSORS_MPU3050_MODULE + .get_slave_descr = NULL,/*ak5883_get_slave_descr,*/ +#else + .get_slave_descr = get_compass_slave_descr, +#endif + .adapt_num = 0, // The i2c bus to which the compass device is. + // It can be difference with mpu + // connected + .irq = RK29_PIN0_PA4, + .bus = EXT_SLAVE_BUS_PRIMARY, + .address = 0x0d, + //.orientation = { -1, 0, 0,0, -1, 0,0, 0, 1 }, + //.orientation = { 0, -1, 0,-1, 0, 0,0, 0, -1 }, + //.orientation = { 0, 1, 0,1, 0, 0,0, 0, -1 }, + .orientation = { 1, 0, 0, 0, -1, 0, 0, 0, -1 }, + }, +#endif +}; +#endif + #if defined (CONFIG_BATTERY_BQ27510) #define DC_CHECK_PIN RK29_PIN4_PA1 #define LI_LION_BAT_NUM 2 @@ -819,6 +934,16 @@ static struct i2c_board_info __initdata board_i2c0_devices[] = { .irq = RK29_PIN0_PA4, }, #endif +/*mpu3050*/ +#if defined (CONFIG_MPU_SENSORS_MPU3050) + { + .type = "mpu3050", + .addr = 0x68, + .flags = 0, + .irq = RK29_PIN5_PA3, + .platform_data = &mpu3050_data, + }, +#endif }; #endif @@ -831,14 +956,6 @@ static struct i2c_board_info __initdata board_i2c1_devices[] = { .flags = 0, }, #endif -#if defined (CONFIG_ANX7150) || defined (CONFIG_ANX7150_NEW) - { - .type = "anx7150", - .addr = 0x39, //0x39, 0x3d - .flags = 0, - .irq = RK29_PIN1_PD7, - }, -#endif }; #endif @@ -876,6 +993,16 @@ static struct i2c_board_info __initdata board_i2c2_devices[] = { }, #endif +#if defined (CONFIG_LAIBAO_TS) + { + .type = "laibao_touch", + .addr = (0x70>>1), + .flags = 0, + .irq = RK29_PIN0_PA2,//gpio_to_irq(RK29_PIN0_PA2), + .platform_data = &laibao_info, + }, +#endif + #if defined (CONFIG_D70_L3188A) { .type = "goodix-ts", @@ -890,6 +1017,15 @@ static struct i2c_board_info __initdata board_i2c2_devices[] = { #ifdef CONFIG_I2C3_RK29 static struct i2c_board_info __initdata board_i2c3_devices[] = { +#if defined (CONFIG_ANX7150) || defined (CONFIG_ANX7150_NEW) + { + .type = "anx7150", + .addr = 0x39, //0x39, 0x3d + .flags = 0, + .irq = RK29_PIN1_PD7, + }, +#endif + }; #endif diff --git a/arch/arm/mach-rk29/include/mach/board.h b/arch/arm/mach-rk29/include/mach/board.h old mode 100755 new mode 100644 index 4697387cbc18..ea11f8be1e70 --- a/arch/arm/mach-rk29/include/mach/board.h +++ b/arch/arm/mach-rk29/include/mach/board.h @@ -280,6 +280,16 @@ struct nas_platform_data { }; +struct laibao_platform_data { + u16 model; + + int (*get_pendown_state)(void); + int (*init_platform_hw)(void); + int (*laibao_platform_sleep)(void); + int (*laibao_platform_wakeup)(void); + void (*exit_platform_hw)(void); +}; + struct akm8975_platform_data { char layouts[3][3]; char project_name[64]; diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig old mode 100755 new mode 100644 index 2fc678712b09..0cb933853a59 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -733,6 +733,12 @@ config TOUCHSCREEN_NAS code includes that in its table of I2C devices. If unsure, say N (but it's safe to say "Y"). + +config LAIBAO_TS + tristate "LAIBAO touchscreen" + depends on I2C2_RK29 + help + RK29 LAIBAO touchscreen config TOUCHSCREEN_GT801_IIC tristate "GT801_IIC based touchscreens" diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 4c05a40954ae..953241e881d3 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -60,3 +60,4 @@ obj-$(CONFIG_D70_L3188A) += goodix_touch.o obj-$(CONFIG_TOUCHSCREEN_FT5406) += ft5406_ts.o obj-$(CONFIG_TOUCHSCREEN_GT819) += gt819.o obj-$(CONFIG_TOUCHSCREEN_NAS) += nas_ts.o +obj-$(CONFIG_LAIBAO_TS) += ft5x0x_i2c_ts.o diff --git a/drivers/input/touchscreen/ft5x0x_i2c_ts.c b/drivers/input/touchscreen/ft5x0x_i2c_ts.c new file mode 100644 index 000000000000..398ca3f4f3e5 --- /dev/null +++ b/drivers/input/touchscreen/ft5x0x_i2c_ts.c @@ -0,0 +1,1024 @@ +/* + * 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. + * + * + * note: only support mulititouch Wenfs 2010-10-01 + */ + +#include +#include +#include +#include +#include +#include "ft5x0x_i2c_ts.h" +#include +#include +#include +#include +#include +#include +/* -------------- global variable definition -----------*/ +static struct i2c_client *this_client; +static REPORT_FINGER_INFO_T _st_finger_infos[CFG_MAX_POINT_NUM]; +//static unsigned int _sui_irq_num= IRQ_EINT(6); +static int _si_touch_num = 0; + +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]; + +/*********************************************************************** + [function]: +callback: read data from ctpm by i2c interface; +[parameters]: +buffer[in]: data buffer; +length[in]: the length of the data buffer; +[return]: +FTS_TRUE: success; +FTS_FALSE: fail; + ************************************************************************/ +static bool i2c_read_interface(u8* pbt_buf, int dw_lenth) +{ + int ret; + + ret=i2c_master_recv(this_client, pbt_buf, dw_lenth); + + if(ret<=0) + { + printk("[TSP]i2c_read_interface error\n"); + return FTS_FALSE; + } + + return FTS_TRUE; +} + + + +/*********************************************************************** + [function]: +callback: write data to ctpm by i2c interface; +[parameters]: +buffer[in]: data buffer; +length[in]: the length of the data buffer; +[return]: +FTS_TRUE: success; +FTS_FALSE: fail; + ************************************************************************/ +static bool i2c_write_interface(u8* pbt_buf, int dw_lenth) +{ + int ret; + ret=i2c_master_send(this_client, pbt_buf, dw_lenth); + if(ret<=0) + { + printk("[TSP]i2c_write_interface error line = %d, ret = %d\n", __LINE__, ret); + return FTS_FALSE; + } + + return FTS_TRUE; +} + + + +/*********************************************************************** + [function]: +callback: read register value ftom ctpm by i2c interface; +[parameters]: +reg_name[in]: the register which you want to read; +rx_buf[in]: data buffer which is used to store register value; +rx_length[in]: the length of the data buffer; +[return]: +FTS_TRUE: success; +FTS_FALSE: fail; + ************************************************************************/ +static bool fts_register_read(u8 reg_name, u8* rx_buf, int rx_length) +{ + u8 read_cmd[2]= {0}; + u8 cmd_len = 0; + + read_cmd[0] = reg_name; + cmd_len = 1; + + /*send register addr*/ + if(!i2c_write_interface(&read_cmd[0], cmd_len)) + { + return FTS_FALSE; + } + + /*call the read callback function to get the register value*/ + if(!i2c_read_interface(rx_buf, rx_length)) + { + return FTS_FALSE; + } + return FTS_TRUE; +} + + + + +/*********************************************************************** + [function]: +callback: read register value ftom ctpm by i2c interface; +[parameters]: +reg_name[in]: the register which you want to write; +tx_buf[in]: buffer which is contained of the writing value; +[return]: +FTS_TRUE: success; +FTS_FALSE: fail; + ************************************************************************/ +static bool fts_register_write(u8 reg_name, u8* tx_buf) +{ + u8 write_cmd[2] = {0}; + + write_cmd[0] = reg_name; + write_cmd[1] = *tx_buf; + + /*call the write callback function*/ + return i2c_write_interface(write_cmd, 2); +} + + + + +/*********************************************************************** + [function]: +callback: report to the input system that the finger is put up; +[parameters]: +null; +[return]: +null; + ************************************************************************/ +static void fts_ts_release(void) +{ + struct FTS_TS_DATA_T *data = i2c_get_clientdata(this_client); + int i; + int i_need_sync = 0; + for ( i= 0; iinput_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 ) + _st_finger_infos[i].u2_pressure= -1; + } + + if (i_need_sync) + { + input_sync(data->input_dev); + } + + _si_touch_num = 0; +} + + + + + + +/*********************************************************************** + [function]: +callback: read touch data ftom ctpm by i2c interface; +[parameters]: +rxdata[in]: data buffer which is used to store touch data; +length[in]: the length of the data buffer; +[return]: +FTS_TRUE: success; +FTS_FALSE: fail; + ************************************************************************/ +static int fts_i2c_rxdata(u8 *rxdata, int length) +{ + int ret; + struct i2c_msg msg; + + + msg.addr = this_client->addr; + msg.flags = 0; + msg.len = 1; + msg.buf = rxdata; + ret = i2c_transfer(this_client->adapter, &msg, 1); + + if (ret < 0) + pr_err("msg %s i2c write error: %d\n", __func__, ret); + + msg.addr = this_client->addr; + msg.flags = I2C_M_RD; + msg.len = length; + msg.buf = rxdata; + ret = i2c_transfer(this_client->adapter, &msg, 1); + if (ret < 0) + pr_err("msg %s i2c write error: %d\n", __func__, ret); + + return ret; +} + + + + + +/*********************************************************************** + [function]: +callback: send data to ctpm by i2c interface; +[parameters]: +txdata[in]: data buffer which is used to send data; +length[in]: the length of the data buffer; +[return]: +FTS_TRUE: success; +FTS_FALSE: fail; + ************************************************************************/ +static int fts_i2c_txdata(u8 *txdata, int length) +{ + int ret; + + struct i2c_msg msg; + + msg.addr = this_client->addr; + msg.flags = 0; + msg.len = length; + msg.buf = txdata; + ret = i2c_transfer(this_client->adapter, &msg, 1); + if (ret < 0) + pr_err("%s i2c write error: %d\n", __func__, ret); + + return ret; +} + + + +/*********************************************************************** + [function]: +callback: gather the finger information and calculate the X,Y +coordinate then report them to the input system; +[parameters]: +null; +[return]: +null; + ************************************************************************/ +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; + + 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]; + + + i_count = 0; + + do + { + buf[0] = 3; + + id = 0xe; + + ret=fts_i2c_rxdata(buf, 6); + 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) + { + + 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; + + //x = (768-x)*600/768; + //y = y*1024/1024; + + swap = x; + x = y; + y = swap; + + //x = 1024 - x;//////////////////////////// + y = 600 - y; + } + + + 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 + } + + 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 + } + + 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 ++; + } + else + /*bad event, ignore*/ + continue; + + + if ( (touch_event==1) ) + { + printk("[TSP]id=%d up\n", id); + } + + + for( i= 0; iinput_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, _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_sync(data->input_dev); + + if (_si_touch_num == 0 ) + { + fts_ts_release(); + } + _si_touch_num = 0; + } + + } + + else + { + printk("[TSP] 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; + } + + return 0; +} + + + +static void fts_work_func(struct work_struct *work) +{ + fts_read_data(); + enable_irq(this_client->irq); +} + + + + +static irqreturn_t fts_ts_irq(int irq, void *dev_id) +{ + struct FTS_TS_DATA_T *ft5x0x_ts = dev_id; + printk(KERN_ALERT "fts_tp_irq\n"); + if (!work_pending(&ft5x0x_ts->pen_event_work)) { + disable_irq_nosync(this_client->irq); + queue_work(ft5x0x_ts->ts_workqueue, &ft5x0x_ts->pen_event_work); + } + + return IRQ_HANDLED; +} + + + +/*********************************************************************** + [function]: +callback: send a command to ctpm. +[parameters]: +btcmd[in]: command code; +btPara1[in]: parameter 1; +btPara2[in]: parameter 2; +btPara3[in]: parameter 3; +num[in]: the valid input parameter numbers, +if only command code needed and no +parameters followed,then the num is 1; +[return]: +FTS_TRUE: success; +FTS_FALSE: io fail; + ************************************************************************/ +static bool cmd_write(u8 btcmd,u8 btPara1,u8 btPara2,u8 btPara3,u8 num) +{ + u8 write_cmd[4] = {0}; + + write_cmd[0] = btcmd; + write_cmd[1] = btPara1; + write_cmd[2] = btPara2; + write_cmd[3] = btPara3; + return i2c_write_interface(write_cmd, num); +} + + + + +/*********************************************************************** + [function]: +callback: write a byte data to ctpm; +[parameters]: +buffer[in]: write buffer; +length[in]: the size of write data; +[return]: +FTS_TRUE: success; +FTS_FALSE: io fail; + ************************************************************************/ +static bool byte_write(u8* buffer, int length) +{ + + return i2c_write_interface(buffer, length); +} + + + + +/*********************************************************************** + [function]: +callback: read a byte data from ctpm; +[parameters]: +buffer[in]: read buffer; +length[in]: the size of read data; +[return]: +FTS_TRUE: success; +FTS_FALSE: io fail; + ************************************************************************/ +static bool byte_read(u8* buffer, int length) +{ + return i2c_read_interface(buffer, length); +} + + + + + +#define FTS_PACKET_LENGTH 128 + +static unsigned char CTPM_FW[]= +{ + //#include "ft_app.i" +}; + + + + +/*********************************************************************** + [function]: +callback: burn the FW to ctpm. +[parameters]: +pbt_buf[in]: point to Head+FW ; +dw_lenth[in]: the length of the FW + 6(the Head length); +[return]: +ERR_OK: no error; +ERR_MODE: fail to switch to UPDATE mode; +ERR_READID: read id fail; +ERR_ERASE: erase chip fail; +ERR_STATUS: status error; +ERR_ECC: ecc error. + ************************************************************************/ +E_UPGRADE_ERR_TYPE fts_ctpm_fw_upgrade(u8* pbt_buf, int dw_lenth) +{ + u8 cmd,reg_val[2] = {0}; + u8 packet_buf[FTS_PACKET_LENGTH + 6]; + u8 auc_i2c_write_buf[10]; + u8 bt_ecc; + + int j,temp,lenght,i_ret,packet_number, i = 0; + int i_is_new_protocol = 0; + + + /******write 0xaa to register 0xfc******/ + cmd=0xaa; + fts_register_write(0xfc,&cmd); + mdelay(50); + + /******write 0x55 to register 0xfc******/ + cmd=0x55; + fts_register_write(0xfc,&cmd); + printk("[TSP] Step 1: Reset CTPM test\n"); + + mdelay(10); + + + /*******Step 2:Enter upgrade mode ****/ + printk("\n[TSP] Step 2:enter new update mode\n"); + auc_i2c_write_buf[0] = 0x55; + auc_i2c_write_buf[1] = 0xaa; + do + { + i ++; + i_ret = fts_i2c_txdata(auc_i2c_write_buf, 2); + mdelay(5); + }while(i_ret <= 0 && i < 10 ); + + if (i > 1) + { + i_is_new_protocol = 1; + } + + /********Step 3:check READ-ID********/ + cmd_write(0x90,0x00,0x00,0x00,4); + byte_read(reg_val,2); + if (reg_val[0] == 0x79 && reg_val[1] == 0x3) + { + printk("[TSP] Step 3: CTPM ID,ID1 = 0x%x,ID2 = 0x%x\n",reg_val[0],reg_val[1]); + } + else + { + return ERR_READID; + //i_is_new_protocol = 1; + } + + + /*********Step 4:erase app**********/ + if (i_is_new_protocol) + { + cmd_write(0x61,0x00,0x00,0x00,1); + } + else + { + cmd_write(0x60,0x00,0x00,0x00,1); + } + mdelay(1500); + printk("[TSP] Step 4: erase. \n"); + + + + /*Step 5:write firmware(FW) to ctpm flash*/ + bt_ecc = 0; + printk("[TSP] Step 5: start upgrade. \n"); + dw_lenth = dw_lenth - 8; + packet_number = (dw_lenth) / FTS_PACKET_LENGTH; + packet_buf[0] = 0xbf; + packet_buf[1] = 0x00; + for (j=0;j>8); + packet_buf[3] = (FTS_BYTE)temp; + lenght = FTS_PACKET_LENGTH; + packet_buf[4] = (FTS_BYTE)(lenght>>8); + packet_buf[5] = (FTS_BYTE)lenght; + + for (i=0;i 0) + { + temp = packet_number * FTS_PACKET_LENGTH; + packet_buf[2] = (FTS_BYTE)(temp>>8); + packet_buf[3] = (FTS_BYTE)temp; + + temp = (dw_lenth) % FTS_PACKET_LENGTH; + packet_buf[4] = (FTS_BYTE)(temp>>8); + packet_buf[5] = (FTS_BYTE)temp; + + for (i=0;i>8); + packet_buf[3] = (FTS_BYTE)temp; + temp =1; + packet_buf[4] = (FTS_BYTE)(temp>>8); + packet_buf[5] = (FTS_BYTE)temp; + packet_buf[6] = pbt_buf[ dw_lenth + i]; + bt_ecc ^= packet_buf[6]; + + byte_write(&packet_buf[0],7); + mdelay(20); + } + + /********send the opration head************/ + cmd_write(0xcc,0x00,0x00,0x00,1); + byte_read(reg_val,1); + printk("[TSP] Step 6: ecc read 0x%x, new firmware 0x%x. \n", reg_val[0], bt_ecc); + if(reg_val[0] != bt_ecc) + { + return ERR_ECC; + } + + /*******Step 7: reset the new FW**********/ + cmd_write(0x07,0x00,0x00,0x00,1); + + return ERR_OK; +} + + + + +int fts_ctpm_fw_upgrade_with_i_file(void) +{ + u8* pbt_buf = FTS_NULL; + int i_ret; + + pbt_buf = CTPM_FW; + i_ret = fts_ctpm_fw_upgrade(pbt_buf,sizeof(CTPM_FW)); + + return i_ret; +} + +unsigned char fts_ctpm_get_upg_ver(void) +{ + unsigned int ui_sz; + + ui_sz = sizeof(CTPM_FW); + if (ui_sz > 2) + { + return CTPM_FW[ui_sz - 2]; + } + else + return 0xff; + +} + + +static int fts_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct FTS_TS_DATA_T *ft5x0x_ts; + struct input_dev *input_dev; + int err = 0; + int _sui_irq_num; + unsigned char reg_value; + unsigned char reg_version; + int i; + + struct laibao_platform_data *pdata = client->dev.platform_data; + + client->irq = gpio_to_irq(client->irq); + _sui_irq_num = client->irq; + + 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; + } + + ft5x0x_ts = kzalloc(sizeof(*ft5x0x_ts), GFP_KERNEL); + if (!ft5x0x_ts) { + err = -ENOMEM; + goto exit_alloc_data_failed; + } + + this_client = client; + i2c_set_clientdata(client, ft5x0x_ts); + + INIT_WORK(&ft5x0x_ts->pen_event_work, fts_work_func); + + ft5x0x_ts->ts_workqueue = create_singlethread_workqueue(dev_name(&client->dev)); + if (!ft5x0x_ts->ts_workqueue) { + err = -ESRCH; + goto exit_create_singlethread; + } + + if (pdata->init_platform_hw) + pdata->init_platform_hw(); + + + + /***wait CTP to bootup normally***/ + 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); + //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); + //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); + //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); + +#if 0 + if (fts_ctpm_get_upg_ver() != reg_version) + { + printk("[TSP] 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"); + 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", + 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); + 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); + 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"); + goto exit_input_dev_alloc_failed; + } + + ft5x0x_ts->input_dev = input_dev; + + /***setup coordinate area******/ + //set_bit(EV_ABS, input_dev->evbit); + //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); + input_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); + + /****** for multi-touch *******/ + for (i=0; ievbit); + //set_bit(EV_KEY, input_dev->evbit); + //set_bit(BTN_TOUCH, input_dev->keybit); + //input_dev->keycode = tsp_keycodes; + //for(i = 0; i < CFG_NUMOFKEYS; i++) + //{ + // input_set_capability(input_dev, EV_KEY, ((int*)input_dev->keycode)[i]); + // tsp_keystatus[i] = KEY_RELEASE; + //} + + input_dev->name = FT5X0X_NAME; + input_dev->id.bustype = BUS_I2C; + input_dev->id.vendor = 0xdead; + input_dev->id.product = 0xbeef; + input_dev->id.version = 10427; + + err = input_register_device(input_dev); + if (err) { + dev_err(&client->dev, + "fts_ts_probe: failed to register input device: %s\n", + dev_name(&client->dev)); + goto exit_input_register_device_failed; + } + + enable_irq(_sui_irq_num); + printk("[TSP] file(%s), function (%s), -- end\n", __FILE__, __FUNCTION__); + return 0; + +exit_input_register_device_failed: + input_free_device(input_dev); +exit_input_dev_alloc_failed: + free_irq(_sui_irq_num, ft5x0x_ts); +exit_irq_request_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_check_functionality_failed: + return err; +} + + + +static int __devexit fts_ts_remove(struct i2c_client *client) +{ + struct FTS_TS_DATA_T *ft5x0x_ts; + int _sui_irq_num=client->irq; + + ft5x0x_ts = (struct FTS_TS_DATA_T *)i2c_get_clientdata(client); + free_irq(_sui_irq_num, ft5x0x_ts); + input_unregister_device(ft5x0x_ts->input_dev); + kfree(ft5x0x_ts); + cancel_work_sync(&ft5x0x_ts->pen_event_work); + destroy_workqueue(ft5x0x_ts->ts_workqueue); + i2c_set_clientdata(client, NULL); + + return 0; +} + +static const struct i2c_device_id ft5x0x_ts_id[] = { + {FT5X0X_NAME, 0}, + {} +}; + + +MODULE_DEVICE_TABLE(i2c, ft5x0x_ts_id); + +static struct i2c_driver fts_ts_driver = { + .probe = fts_ts_probe, + .remove = fts_ts_remove,//devexit_p(fts_ts_remove), + .id_table = ft5x0x_ts_id, + .driver = { + .name = FT5X0X_NAME, + }, +}; + +static void __init fts_ts_initasync(void *unused, async_cookie_t cookie) +{ + i2c_add_driver(&fts_ts_driver); +} + +static int __init fts_ts_init(void) +{ + async_schedule(fts_ts_initasync, NULL); + return 0; +} + +static void __exit fts_ts_exit(void) +{ + i2c_del_driver(&fts_ts_driver); +} + +module_init(fts_ts_init); +module_exit(fts_ts_exit); + +MODULE_AUTHOR(""); +MODULE_DESCRIPTION("FocalTech ft5x0x TouchScreen driver"); +MODULE_LICENSE("GPL"); + diff --git a/drivers/input/touchscreen/ft5x0x_i2c_ts.h b/drivers/input/touchscreen/ft5x0x_i2c_ts.h new file mode 100644 index 000000000000..10eb263cb55d --- /dev/null +++ b/drivers/input/touchscreen/ft5x0x_i2c_ts.h @@ -0,0 +1,121 @@ +#ifndef __LINUX_FT5X0X_TS_H__ +#define __LINUX_FT5X0X_TS_H__ + +//#define CONFIG_SUPPORT_FTS_CTP_UPG +#define CONFIG_FTS_CUSTOME_ENV + +#define CFG_DBG_DUMMY_INFO_SUPPORT 1 //output touch point information +#define CFG_DBG_FUCTION_INFO_SUPPORT 0 //output fouction name +#define CFG_DBG_INPUT_EVENT 0 //debug input event + + +#define CFG_MAX_POINT_NUM 0x5 //max touch points supported +#define CFG_NUMOFKEYS 0x4 //number of touch keys + +#ifdef CONFIG_FTS_CUSTOME_ENV +#define SCREEN_MAX_X 1024 +#define SCREEN_MAX_Y 600 +#else +#define SCREEN_MAX_X 800 +#define SCREEN_MAX_Y 480 +#endif +#define PRESS_MAX 255 + +#define KEY_PRESS 0x1 +#define KEY_RELEASE 0x0 + +#define FT5X0X_NAME "laibao_touch"//"ft5x0x_ts" + +#define FTS_NULL 0x0 +#define FTS_TRUE 0x1 +#define FTS_FALSE 0x0 +#define I2C_CTPM_ADDRESS 0x70 + +typedef unsigned char FTS_BYTE; +typedef unsigned short FTS_WORD; +typedef unsigned int FTS_DWRD; +typedef unsigned char FTS_BOOL; + + + + typedef struct _REPORT_FINGER_INFO_T + { + short ui2_id; /* ID information, from 0 to CFG_MAX_POINT_NUM - 1*/ + short u2_pressure; /* ***pressure information, valid from 0 -63 **********/ + short i2_x; /*********** X coordinate, 0 - 2047 ****************/ + short i2_y; /* **********Y coordinate, 0 - 2047 ****************/ + } REPORT_FINGER_INFO_T; + + +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; + + + struct FTS_TS_EVENT_T { + short x1; + short y1; + short x2; + short y2; + short x3; + short y3; + short x4; + short y4; + short x5; + short y5; + short pressure1; + short pressure2; + short pressure3; + short pressure4; + short pressure5; + u8 touch_point; +}; + +struct FTS_TS_DATA_T { + struct input_dev *input_dev; + struct FTS_TS_EVENT_T event; + struct work_struct pen_event_work; + struct workqueue_struct *ts_workqueue; +}; + + + +enum ft5x0x_ts_regs { + FT5X0X_REG_THRES = 0x80, /* Thresshold, the threshold be low, the sensitivy will be high */ + FT5X0X_REG_REPORT_RATE = 0x88, /* **************report rate, in unit of 10Hz **************/ + FT5X0X_REG_PMODE = 0xA5, /* Power Consume Mode 0 -- active, 1 -- monitor, 3 -- sleep */ + FT5X0X_REG_FIRMID = 0xA6, /* ***************firmware version **********************/ + FT5X0X_REG_NOISE_MODE = 0xb2 /* to enable or disable power noise, 1 -- enable, 0 -- disable */ +}; + +#define PMODE_ACTIVE 0x00 +#define PMODE_MONITOR 0x01 +#define PMODE_STANDBY 0x02 +#define PMODE_HIBERNATE 0x03 + + +#ifndef ABS_MT_TOUCH_MAJOR +#define ABS_MT_TOUCH_MAJOR 0x30 /* touching ellipse */ +#define ABS_MT_TOUCH_MINOR 0x31 /* (omit if circular) */ +#define ABS_MT_WIDTH_MAJOR 0x32 /* approaching ellipse */ +#define ABS_MT_WIDTH_MINOR 0x33 /* (omit if circular) */ +#define ABS_MT_ORIENTATION 0x34 /* Ellipse orientation */ +#define ABS_MT_POSITION_X 0x35 /* Center X ellipse position */ +#define ABS_MT_POSITION_Y 0x36 /* Center Y ellipse position */ +#define ABS_MT_TOOL_TYPE 0x37 /* Type of touching device */ +#define ABS_MT_BLOB_ID 0x38 /* Group set of pkts as blob */ +#endif + + +#endif + + -- 2.34.1