全志A33之添加电容触摸GT911驱动

基于锐尔威视的A33开发板及提供的开发包,仅供参考。

开发板说是支持GT911,其实是不支持的,得修改驱动及配置,启动文件。

一.      修改配置文件

/home/yygyickl/A33/dragonboard/tools/pack/chips/sun8iw5p1/configs/vstar/sys_config.fex     这是我的目录。

触摸部分修改为下面的样子。

[ctp_para]

ctp_used            = 1

ctp_name            = "gt9xx_ts"

ctp_twi_id          = 0

ctp_twi_addr        = 0x5d

ctp_screen_max_x    = 1024

ctp_screen_max_y    = 600

ctp_revert_x_flag   = 0

ctp_revert_y_flag   = 0

ctp_exchange_x_y_flag= 0

ctp_int_port        =port:PB05<4><default><default><default>

ctp_wakeup          =port:PH01<1><default><default><1>

;ctp_power_ldo       = "axp22_eldo1"

;ctp_power_ldo_vol   = 3000

;ctp_power_io        =

;--------------------------------------------------------------------------------

; CTP automaticdetection configuration

;ctp_detect_used  --- Whether startup automatic inspectionfunction. 1:used,0:unused

;Module namepostposition 1 said detection, 0 means no detection.

;--------------------------------------------------------------------------------

[ctp_list_para]

ctp_det_used              = 0

ft5x_ts                   = 0

gt82x                     = 0

gslX680                   = 0

gslX680new                = 0

gt9xx_ts                  = 1

gt9xxf_ts                 = 0

tu_ts                     = 0

gt818_ts                  = 0

zet622x                   = 0

aw5306_ts                 = 0

icn83xx_ts                = 0

仅支持GT911。

二.      修改启动文件

/home/yygyickl/A33/dragonboard/buildroot/target/dragonboard/extra/autorun.sh     这是我的目录。

将触摸部分的insmod"$tp_module_path" 修改为

insmod     /system/vendor/modules/gt9xx_ts.ko

下面这部分中的ft5x_ts全部替换为gt9xx_ts

#tslib config

export TSLIB_CALIBFILE=/etc/pointercal

TS_INFO_FILE1=/sys/class/input/event3/device/name

TS_INFO_FILE2=/sys/class/input/event4/device/name

if grep -q ft5x_ts $TS_INFO_FILE1; then

export TSLIB_TSDEVICE=/dev/input/event3

export QWS_MOUSE_PROTO="Tslib:/dev/input/event3MouseMan:/dev/input/mouse0"

if [ ! -s "$TSLIB_CALIBFILE" ];then

rm -f $TSLIB_CALIBFILE

fi

elif grep -q ft5x_ts $TS_INFO_FILE2; then

export TSLIB_TSDEVICE=/dev/input/event4

export QWS_MOUSE_PROTO="Tslib:/dev/input/event4MouseMan:/dev/input/mouse0"

if [ ! -s "$TSLIB_CALIBFILE" ]; then

rm -f $TSLIB_CALIBFILE

fi

else

export QWS_MOUSE_PROTO=MouseMan:/dev/input/mouse0 > $TSLIB_CALIBFILE

fi

unset TS_INFO_FILE1

unset TS_INFO_FILE2

三.      修改驱动

/home/yygyickl/A33/dragonboard/Linux-3.4/Drivers/Input/Touchscreen/Gt9xx/    进入目录

修改Gt9xx_ts.h为:

#ifndef _LINUX_GOODIX_TOUCH_H

#define  _LINUX_GOODIX_TOUCH_H

#include <linux/kernel.h>

#include <linux/hrtimer.h>

#include <linux/i2c.h>

#include <linux/input.h>

#include <linux/module.h>

#include <linux/delay.h>

#include <linux/i2c.h>

#include <linux/proc_fs.h>

#include <linux/string.h>

#include <asm/uaccess.h>

#include <linux/vmalloc.h>

#include <linux/interrupt.h>

#include <linux/io.h>

#ifdef CONFIG_HAS_EARLYSUSPEND

#include <linux/earlysuspend.h>

#endif

#include <linux/device.h>

#include <linux/slab.h>

#include <linux/init.h>

#include <linux/errno.h>

#include <linux/platform_device.h>

#include <linux/async.h>

#include <linux/ioport.h>

#include <asm/irq.h>

#include <asm/delay.h>

#include <linux/irq.h>

#include <linux/gpio.h>

#include <mach/irqs.h>

#include <mach/hardware.h>

#include <mach/sys_config.h>

#include <linux/init-input.h>

#include <linux/pinctrl/consumer.h>

#include<linux/pinctrl/pinconf-sunxi.h>

struct gt9xx_event {

inttouch_point;

u16x[5];

u16y[5];

u16w[5];

};

struct goodix_ts_data {

spinlock_t irq_lock;

struct i2c_client *client;

struct input_dev  *input_dev;

structgt9xx_event event;

struct hrtimer timer;

struct work_struct  work;

#ifdef CONFIG_HAS_EARLYSUSPEND

struct early_suspend early_suspend;

#endif

s32 irq_is_disable;

s32 use_irq;

u16 abs_x_max;

u16 abs_y_max;

u8  max_touch_num;

u8  int_trigger_type;

u8  green_wake_mode;

u8  enter_update;

u8  gtp_is_suspend;

u8  gtp_rawdiff_mode;

int  gtp_cfg_len;

u8  fw_error;

u8  pnl_init_error;

#if  defined(CONFIG_FB)

structnotifier_block notifier;

#elif defined(CONFIG_HAS_EARLYSUSPEND)

structearly_suspend early_suspend;

#endif

};

extern u16 show_len;

extern u16 total_len;

extern struct ctp_config_info config_info;

//***************************PART1:ON/OFFdefine*******************************

#define GTP_CUSTOM_CFG        1

#define GTP_CHANGE_X2Y        0      //swap x y

#define GTP_DRIVER_SEND_CFG   1     //driver send config     此开关根据需要选择

#define GTP_CONFIG_MODE         0       //触摸屏本来是好的,没有厂家数据表的情况下:0=从GT911中读原来的配置参数,修改后再配置

//有厂家数据表的情况 1:修改数据表后配置

#define GTP_HAVE_TOUCH_KEY    0

#define GTP_POWER_CTRL_SLEEP  0   //power off when suspend

#define GTP_ICS_SLOT_REPORT   0   // slot protocol

#define GTP_AUTO_UPDATE       0   // auto update fw by .bin file as default

#define GTP_HEADER_FW_UPDATE  0    //auto update fw by gtp_default_FW in gt9xx_firmware.h, function together withGTP_AUTO_UPDATE

#define GTP_AUTO_UPDATE_CFG   0   // auto update config by .cfg file, function together withGTP_AUTO_UPDATE

#define GTP_COMPATIBLE_MODE   0   // compatible with GT9XXF

#define GTP_CREATE_WR_NODE    0

#define GTP_ESD_PROTECT       0   // esd protection with a cycle of 2 seconds

#define GTP_WITH_PEN          0

#define GTP_PEN_HAVE_BUTTON   0   // active pen has buttons, function together with GTP_WITH_PEN

#define GTP_GESTURE_WAKEUP    0   // gesture wakeup

#define GTP_DEBUG_ON          1

#define GTP_DEBUG_ARRAY_ON    0

#define GTP_DEBUG_FUNC_ON     0

//***************************PART2:TODOdefine**********************************

//STEP_1(REQUIRED):Change config table.

/*TODO: puts the config info correspondedto your TP here, the following is just

a sample config, send this config shouldcause the chip cannot work normally*/

//default or float

// sochip,ma805d5 ,768*1024,gt911,COB

#define CTP_CFG_GROUP0    {\

0x42,0x00,0x04,0x58,0x02,0x05,0x3D,0x00,0x01,0x08,\

0x28,0x08,0x50,0x3C,0x03,0x05,0x00,0x00,0x00,0x00,\

0x00,0x00,0x00,0x18,0x1A,0x1E,0x14,0x89,0x2A,0x0B,\

0x40,0x42,0xB5,0x06,0x00,0x00,0x00,0x02,0x02,0x1D,\

0x00,0x01,0x00,0x00,0x00,0x03,0x64,0x00,0x00,0x00,\

0x00,0x32,0x5A,0x94,0xC5,0x02,0x08,0x00,0x00,0x00,\

0x98,0x35,0x00,0x8A,0x3B,0x00,0x7A,0x43,0x00,0x6E,\

0x4B,0x00,0x62,0x55,0x00,0x62,0x00,0x00,0x00,0x00,\

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\

0x00,0x00,0x02,0x04,0x06,0x08,0x0A,0x0C,0x0E,0x10,\

0x12,0x14,0x16,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,\

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\

0x00,0x00,0x00,0x02,0x04,0x06,0x08,0x0A,0x0F,0x10,\

0x12,0x16,0x18,0x1C,0x1D,0x1E,0x1F,0x20,0x21,0x22,\

0x24,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,\

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\

0x00,0x00,0x00,0x00,0x60,0x01}

//#define GTP_RST_PORT    S5PV210_GPJ3(6)

//#define GTP_INT_PORT    S5PV210_GPH1(3)

//#define GTP_INT_IRQ     SW_INT_IRQNO_PIO

//#define GTP_INT_CFG     S3C_GPIO_SFN(0xF)

//#ifdef CONFIG_ARCH_SUN4I

//#define CTP_IRQ_NO               (IRQ_EINT21)

//#elif defined CONFIG_ARCH_SUN5I

//#define CTP_IRQ_NO               (IRQ_EINT9)

//#endif

//#define CTP_IRQ_MODE                (TRIG_EDGE_NEGATIVE)

#define GTP_GPIO_AS_INPUT(pin)          do{\

gpio_direction_input(pin);\

s3c_gpio_setpull(pin, S3C_GPIO_PULL_NONE);\

}while(0)

#define GTP_GPIO_AS_INT(pin)            do{\

GTP_GPIO_AS_INPUT(pin);\

s3c_gpio_cfgpin(pin,GTP_INT_CFG);\

}while(0)

#define GTP_GPIO_GET_VALUE(pin)         gpio_get_value(pin)

#define GTP_GPIO_OUTPUT(pin,level)      gpio_direction_output(pin,level)

#define GTP_GPIO_REQUEST(pin, label)    gpio_request(pin, label)

#define GTP_GPIO_FREE(pin)              gpio_free(pin)

#define GTP_IRQ_TAB                     {IRQ_TYPE_EDGE_RISING,IRQ_TYPE_EDGE_FALLING, IRQ_TYPE_LEVEL_LOW, IRQ_TYPE_LEVEL_HIGH}

//STEP_3(optional):Custom set some configby themself,if need.

#if GTP_CUSTOM_CFG

#define GTP_MAX_HEIGHT   600

#define GTP_MAX_WIDTH    1024

#define GTP_INT_TRIGGER  1    //0:Rising 1:Falling

#else

#define GTP_MAX_HEIGHT   4096

#define GTP_MAX_WIDTH    4096

#define GTP_INT_TRIGGER  1

#endif

#define GTP_MAX_TOUCH         5

#define GTP_ESD_CHECK_CIRCLE  2000

//STEP_4(optional):If this project havetouch key,Set touch key config.

#if GTP_HAVE_TOUCH_KEY

#define GTP_KEY_TAB     {KEY_MENU,KEY_HOME, KEY_BACK, KEY_SEND}

#endif

//***************************PART3:OTHERdefine*********************************

#define GTP_DRIVER_VERSION    "V2.4<2014/11/28>"

#define GTP_I2C_NAME          "gt9xx_ts"

#define GTP_POLL_TIME         10

#define GTP_ADDR_LENGTH       2

#define GTP_CONFIG_MIN_LENGTH 186

#define GTP_CONFIG_MAX_LENGTH 240

#define FAIL                  0

#define SUCCESS               1

//Register define

#define GTP_READ_COOR_ADDR    0x814E

#define GTP_REG_SLEEP         0x8040

#define GTP_REG_SENSOR_ID     0x814A

#define GTP_REG_CONFIG_DATA   0x8047

#define GTP_REG_VERSION       0x8140

#define GTP_REG_COMMAND       0x8040

#define GTP_COMMAND_READSTATUS            0

#define GTP_COMMAND_DIFFERENCE         1

#define GTP_COMMAND_SOFTRESET              2

#define GTP_COMMAND_UPDATE                    3

#define GTP_COMMAND_CALCULATE           4

#define GTP_COMMAND_TURNOFF                    5

#define RESOLUTION_LOC        3

#define TRIGGER_LOC           8

//Log define

#define GTP_INFO(fmt,arg...)          printk("<<-GTP-INFO->> "fmt"\n",##arg)

#define GTP_ERROR(fmt,arg...)         printk("<<-GTP-ERROR->> "fmt"\n",##arg)

#define GTP_DEBUG(fmt,arg...)          do{\

if(GTP_DEBUG_ON)\

printk("<<-GTP-DEBUG->>[%d]"fmt"\n",__LINE__, ##arg);\

}while(0)

#define GTP_DEBUG_ARRAY(array, num)    do{\

s32i;\

u8* a = array;\

if(GTP_DEBUG_ARRAY_ON)\

{\

printk("<<-GTP-DEBUG-ARRAY->>\n");\

for (i = 0; i < (num); i++)\

{\

printk("%02x   ",(a)[i]);\

if ((i + 1 ) %10 == 0)\

{\

printk("\n");\

}\

}\

printk("\n");\

}\

}while(0)

#define GTP_DEBUG_FUNC()               do{\

if(GTP_DEBUG_FUNC_ON)\

printk("<<-GTP-FUNC->>Func:%s@Line:%d\n",__func__,__LINE__);\

}while(0)

#define GTP_SWAP(x, y)                 do{\

typeof(x) z = x;\

x =y;\

y = z;\

}while(0)

//****************************PART4:UPDATEdefine*******************************

//Error no

#define ERROR_NO_FILE           2  //ENOENT

#define ERROR_FILE_READ         23 //ENFILE

#define ERROR_FILE_TYPE         21 //EISDIR

#define ERROR_GPIO_REQUEST      4  //EINTR

#define ERROR_I2C_TRANSFER      5  //EIO

#define ERROR_NO_RESPONSE       16 //EBUSY

#define ERROR_TIMEOUT           110 //ETIMEDOUT

//*****************************End of PartIII********************************

#endif /* _LINUX_GOODIX_TOUCH_H */

修改gt9xx.c为:

#include <linux/irq.h>

#include "gt9xx_ts.h"

#include <linux/pm.h>

#if GTP_ICS_SLOT_REPORT

#include <linux/input/mt.h>

#endif

static const char *goodix_ts_name ="gt9xx";

static struct workqueue_struct *goodix_wq;

struct i2c_client * i2c_connect_client =NULL;

static u8 config[GTP_CONFIG_MAX_LENGTH +GTP_ADDR_LENGTH]

= {GTP_REG_CONFIG_DATA >>8, GTP_REG_CONFIG_DATA & 0xff};

#if GTP_HAVE_TOUCH_KEY

staticconst u16 touch_key_array[] = GTP_KEY_TAB;

#defineGTP_MAX_KEY_NUM      (sizeof(touch_key_array)/sizeof(touch_key_array[0]))

#endif

static s8 gtp_i2c_test(struct i2c_client*client);

void gtp_reset_guitar(struct i2c_client*client, s32 ms);

void gtp_int_sync(s32 ms);

#ifdef CONFIG_HAS_EARLYSUSPEND

static void goodix_ts_early_suspend(structearly_suspend *h);

static void goodix_ts_late_resume(structearly_suspend *h);

#endif

#if GTP_CREATE_WR_NODE

extern s32 init_wr_node(structi2c_client*);

extern void uninit_wr_node(void);

#endif

#if GTP_AUTO_UPDATE

extern u8 gup_init_update_proc(structgoodix_ts_data *);

#endif

#if GTP_ESD_PROTECT

static struct delayed_workgtp_esd_check_work;

static struct workqueue_struct *gtp_esd_check_workqueue = NULL;

static void gtp_esd_check_func(structwork_struct *);

s32 gtp_init_ext_watchdog(structi2c_client *client);

#endif

///

//specific tp related macro: need beconfigured for specific tp

#define CTP_IRQ_NUMBER          (config_info.int_number)

#define CTP_IRQ_MODE        (IRQF_TRIGGER_FALLING)

#define CTP_NAME         ("gt9xx_ts")

#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 twi_id = 0;

static char irq_pin_name[8];

static u32 debug_mask = 0;

enum{

DEBUG_INIT= 1U << 0,

DEBUG_SUSPEND= 1U << 1,

DEBUG_INT_INFO= 1U << 2,

DEBUG_X_Y_INFO= 1U << 3,

DEBUG_KEY_INFO= 1U << 4,

DEBUG_WAKEUP_INFO= 1U << 5,

DEBUG_OTHERS_INFO= 1U << 6,

};

#definedprintk(level_mask,fmt,arg...)   if(unlikely(debug_mask & level_mask)) \

printk("***CTP***"fmt, ## arg)

module_param_named(debug_mask,debug_mask,int,S_IRUGO| S_IWUSR | S_IWGRP);

static const unsigned short normal_i2c[2]= {0x5d, I2C_CLIENT_END};

//static const int chip_id_value[3] ={57};

//static uint8_t read_chip_value[3] ={GTP_REG_VERSION >> 8, GTP_REG_VERSION & 0xff,0};

struct ctp_config_info config_info = {

.input_type= CTP_TYPE,

.name= NULL,

.int_number= 0,

};

//static void goodix_init_events(structwork_struct *work);

static void goodix_resume_events(structwork_struct *work);

static struct workqueue_struct *goodix_wq;

//static struct workqueue_struct*goodix_init_wq;

static struct workqueue_struct*goodix_resume_wq;

//static DECLARE_WORK(goodix_init_work,goodix_init_events);

static DECLARE_WORK(goodix_resume_work,goodix_resume_events);

/**

*ctp_detect - Device detection callback for automatic device creation

*return value:

*                    = 0; success;

*                    < 0; err

*/

static int ctp_detect(struct i2c_client*client, struct i2c_board_info *info)

{

structi2c_adapter *adapter = client->adapter;

int  ret = -1;

if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)){

printk("======return=====\n");

return -ENODEV;

}

if(twi_id == adapter->nr){

dprintk(DEBUG_INIT,"%s: addr = %x\n", __func__,client->addr);

ret = gtp_i2c_test(client);

printk("detectret %d\n",ret);

if(!ret){

printk("%s:I2Cconnection might be something wrong \n", __func__);

return -ENODEV;

}else{

strlcpy(info->type, CTP_NAME,I2C_NAME_SIZE);

printk("======detectok !=====\n");

return0;

}

}else{

return -ENODEV;

}

}

/**

*ctp_print_info - sysconfig print function

*return value:

*

*/

void ctp_print_info(struct ctp_config_infoinfo,int debug_level)

{

if(debug_level== DEBUG_INIT)

{

dprintk(DEBUG_INIT,"info.ctp_used:%d\n",info.ctp_used);

dprintk(DEBUG_INIT,"info.twi_id:%d\n",info.twi_id);

dprintk(DEBUG_INIT,"info.screen_max_x:%d\n",info.screen_max_x);

dprintk(DEBUG_INIT,"info.screen_max_y:%d\n",info.screen_max_y);

dprintk(DEBUG_INIT,"info.revert_x_flag:%d\n",info.revert_x_flag);

dprintk(DEBUG_INIT,"info.revert_y_flag:%d\n",info.revert_y_flag);

dprintk(DEBUG_INIT,"info.exchange_x_y_flag:%d\n",info.exchange_x_y_flag);

dprintk(DEBUG_INIT,"info.irq_gpio_number:%d\n",info.irq_gpio.gpio);

dprintk(DEBUG_INIT,"info.wakeup_gpio_number:%d\n",info.wakeup_gpio.gpio);

}

}

/**

*ctp_wakeup - function

*

*/

int ctp_wakeup(int status,int ms)

{

dprintk(DEBUG_INIT,"***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);

return0;

}

void gtp_set_int_value(int status)

{

long unsigned int config;

config= SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_FUNC,0xFFFF);

pin_config_get(SUNXI_PINCTRL,irq_pin_name,&config);

if(1 != SUNXI_PINCFG_UNPACK_VALUE(config)){

config =SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_FUNC,1);

pin_config_set(SUNXI_PINCTRL,irq_pin_name,config);;

}

__gpio_set_value(CTP_IRQ_NUMBER, status);

}

void gtp_set_io_int(void)

{

long unsigned int config;

config= SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_FUNC,0xFFFF);

pin_config_get(SUNXI_PINCTRL,irq_pin_name,&config);

if(4 != SUNXI_PINCFG_UNPACK_VALUE(config)){

config =SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_FUNC,4);

pin_config_set(SUNXI_PINCTRL,irq_pin_name,config);

}

}

/*******************************************************

Function:

Synchronization.

Input:

ms: synchronization time in millisecond.

Output:

None.

*******************************************************/

void gtp_int_sync(s32 ms)

{

gtp_set_int_value(0);

msleep(ms);

gtp_set_io_int();

}

/*******************************************************

Function:

Reset chip.

Input:

ms: reset time in millisecond

Output:

None.

*******************************************************/

void gtp_reset_guitar(struct i2c_client*client, s32 ms)

{

#if GTP_COMPATIBLE_MODE

struct goodix_ts_data *ts = i2c_get_clientdata(client);

#endif

GTP_DEBUG_FUNC();

GTP_INFO("Guitar reset");

ctp_wakeup(0, 0);   // beginselect I2C slave addr

msleep(ms);                        // T2: > 10ms

// HIGH: 0x28/0x29, LOW: 0xBA/0xBB

gtp_set_int_value(0);

msleep(2);                         // T3: > 100us

ctp_wakeup(1, 0);

msleep(6);                         // T4: > 5ms

// GTP_GPIO_AS_INPUT(gtp_rst_gpio);   // end select I2C slave addr

#if GTP_COMPATIBLE_MODE

if (CHIP_TYPE_GT9F == ts->chip_type)

{

return;

}

#endif

gtp_int_sync(50);

#if GTP_ESD_PROTECT

gtp_init_ext_watchdog(client);

#endif

}

void gtp_io_init(int ms)

{

ctp_wakeup(0, 0);

msleep(ms);

gtp_set_int_value(0);

msleep(2);

ctp_wakeup(1, 0);

msleep(6);

gtp_int_sync(50);

#if GTP_ESD_PROTECT

//  gtp_init_ext_watchdog(client);

#endif

}

/*******************************************************

Function:

Readdata from the i2c slave device.

Input:

client:   i2c device.

buf[0]:operateaddress.

buf[1]~buf[len]:readdata buffer.

len:operatelength.

Output:

numbersof i2c_msgs to transfer

*********************************************************/

s32 gtp_i2c_read(struct i2c_client*client, u8 *buf, s32 len)

{

struct i2c_msg msgs[2];

s32 ret = -1;

s32 retries = 0;

msgs[0].flags = !I2C_M_RD;

msgs[0].addr  = client->addr;

msgs[0].len   = GTP_ADDR_LENGTH;

msgs[0].buf   = &buf[0];

msgs[1].flags = I2C_M_RD;

msgs[1].addr  = client->addr;

msgs[1].len   = len -GTP_ADDR_LENGTH;

msgs[1].buf   = &buf[GTP_ADDR_LENGTH];

while(retries < 5) {

ret =i2c_transfer(client->adapter, msgs, 2);

if(ret == 2)

break;

retries++;

}

if(retries >= 5) {

printk("%s:I2C retrytimeout, reset chip.", __func__);

gtp_reset_guitar(client,10);

}

return ret;

}

/*******************************************************

Function:

writedata to the i2c slave device.

Input:

client:   i2c device.

buf[0]:operateaddress.

buf[1]~buf[len]:writedata buffer.

len:operatelength.

Output:

numbersof i2c_msgs to transfer.

*********************************************************/

s32 gtp_i2c_write(struct i2c_client*client,u8 *buf,s32 len)

{

struct i2c_msg msg;

s32 ret = -1;

s32 retries = 0;

msg.flags = !I2C_M_RD;

msg.addr  = client->addr;

msg.len   = len;

msg.buf   = buf;

while(retries < 5) {

ret =i2c_transfer(client->adapter, &msg, 1);

if (ret == 1)

break;

retries++;

}

if(retries >= 5) {

printk("%s:I2C retry timeout,reset chip.", __func__);

gtp_reset_guitar(client,10);

}

return ret;

}

/*******************************************************

Function:

i2c read twice, compare the results

Input:

client:  i2c device

addr:    operate address

rxbuf:   read data to store, ifcompare successful

len:     bytes to read

Output:

FAIL:    read failed

SUCCESS: read successful

*********************************************************/

s32 gtp_i2c_read_dbl_check(structi2c_client *client, u16 addr, u8 *rxbuf, int len)

{

u8 buf[16] = {0};

u8 confirm_buf[16] = {0};

u8 retry = 0;

while (retry++ < 3)

{

memset(buf, 0xAA, 16);

buf[0] = (u8)(addr >> 8);

buf[1] = (u8)(addr & 0xFF);

gtp_i2c_read(client, buf, len + 2);

memset(confirm_buf, 0xAB, 16);

confirm_buf[0] = (u8)(addr >> 8);

confirm_buf[1] = (u8)(addr & 0xFF);

gtp_i2c_read(client, confirm_buf, len + 2);

if (!memcmp(buf, confirm_buf, len+2))

{

memcpy(rxbuf, confirm_buf+2, len);

return SUCCESS;

}

}

GTP_ERROR("I2C read 0x%04X, %d bytes, double check failed!",addr, len);

return FAIL;

}

/*******************************************************

Function:

i2c read config data check it

Input:

client:  i2c device

Output:

FAIL:    read failed

SUCCESS: read successful

*********************************************************/

void gtp_i2c_read_cfg_check(structi2c_client *client)

{

structgoodix_ts_data *ts = i2c_get_clientdata(client);

u8buf[GTP_CONFIG_MIN_LENGTH + GTP_ADDR_LENGTH];

u8retry = 0;

memset(buf,0, ts->gtp_cfg_len + GTP_ADDR_LENGTH);

buf[0]= config[0];

buf[1]= config[1];

gtp_i2c_read(client,buf, ts->gtp_cfg_len + GTP_ADDR_LENGTH);

GTP_DEBUG_ARRAY(buf+GTP_ADDR_LENGTH,ts->gtp_cfg_len);

if(memcmp(buf+GTP_ADDR_LENGTH,config+GTP_ADDR_LENGTH, ts->gtp_cfg_len-1) == 0)

{

GTP_INFO("cfgcheck ok!\r\n");

returnSUCCESS;

}

else

{

GTP_INFO("cfgcheck failed!\r\n");

returnFAIL;

}

}

/*******************************************************

Function:

Sendconfig Function.

Input:

client:   i2c client.

Output:

Executiveoutcomes.0--success,non-0--fail.

*******************************************************/

s32 gtp_send_cfg(struct i2c_client*client)

{

s32 ret = 0;

#if GTP_DRIVER_SEND_CFG

s32 retry = 0;

for (retry = 0; retry < 5; retry++)

{

ret = gtp_i2c_write(client, config , GTP_CONFIG_MAX_LENGTH +GTP_ADDR_LENGTH);

if (ret > 0)

{

break;

}

}

#endif

return ret;

}

/*******************************************************

Function:

DisableIRQ Function.

Input:

ts:  i2c client private struct.

Output:

None.

*******************************************************/

void gtp_irq_disable(struct goodix_ts_data*ts)

{

unsigned long irqflags;

intret;

dprintk(DEBUG_INT_INFO, "%s ---start!---\n", __func__);

spin_lock_irqsave(&ts->irq_lock, irqflags);

if (!ts->irq_is_disable) {

ts->irq_is_disable = 1;

ret =input_set_int_enable(&(config_info.input_type), 0);

if (ret < 0)

dprintk(DEBUG_OTHERS_INFO,"%s irqdisable failed\n", goodix_ts_name);

}

spin_unlock_irqrestore(&ts->irq_lock, irqflags);

}

/*******************************************************

Function:

DisableIRQ Function.

Input:

ts:  i2c client private struct.

Output:

None.

*******************************************************/

void gtp_irq_enable(struct goodix_ts_data*ts)

{

unsigned long irqflags = 0;

intret;

dprintk(DEBUG_INT_INFO, "%s ---start!---\n", __func__);

spin_lock_irqsave(&ts->irq_lock, irqflags);

if (ts->irq_is_disable) {

ts->irq_is_disable = 0;

ret =input_set_int_enable(&(config_info.input_type), 1);

if(ret < 0)

dprintk(DEBUG_OTHERS_INFO,"%sirq enable failed\n", goodix_ts_name);

}

spin_unlock_irqrestore(&ts->irq_lock, irqflags);

}

/*******************************************************

Function:

Touchdown report function.

Input:

ts:privatedata.

id:trackingid.

x:inputx.

y:inputy.

w:inputweight.

Output:

None.

*******************************************************/

static void gtp_touch_down(structgoodix_ts_data* ts,s32 id,s32 x,s32 y,s32 w)

{

dprintk(DEBUG_X_Y_INFO, "source data:ID:%d, X:%d, Y:%d,W:%d\n", id, x, y, w);

if(1 == exchange_x_y_flag){

swap(x, y);

}

if(1 == revert_x_flag){

x = SCREEN_MAX_X - x;

}

if(1 == revert_y_flag){

y = SCREEN_MAX_Y - y;

}

dprintk(DEBUG_X_Y_INFO,"report data:ID:%d, X:%d, Y:%d,W:%d\n", id, x, y, w);

#if GTP_ICS_SLOT_REPORT

input_mt_slot(ts->input_dev, id);

input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, id);

input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x);

input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y);

input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, w);

input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, w);

#else

input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x);

input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y);

input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, w);

input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, w);

input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, id);

input_mt_sync(ts->input_dev);

#endif

}

/*******************************************************

Function:

Touchup report function.

Input:

ts:privatedata.

Output:

None.

*******************************************************/

static void gtp_touch_up(structgoodix_ts_data* ts, s32 id)

{

#if GTP_ICS_SLOT_REPORT

input_mt_slot(ts->input_dev, id);

input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, -1);

dprintk(DEBUG_X_Y_INFO, "Touch id[%2d] release!", id);

#else

input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0);

input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0);

input_mt_sync(ts->input_dev);

#endif

}

/*******************************************************

Function:

Goodixtouchscreen work function.

Input:

work:    work_struct of goodix_wq.

Output:

None.

*******************************************************/

static void goodix_ts_work_func(structwork_struct *work)

{

u8  end_cmd[3] ={GTP_READ_COOR_ADDR >> 8, GTP_READ_COOR_ADDR & 0xFF, 0};

u8  point_data[2 + 1 + 8 *GTP_MAX_TOUCH + 1]={GTP_READ_COOR_ADDR >> 8, GTP_READ_COOR_ADDR &0xFF};

u8  touch_num = 0;

u8  finger = 0;

static u16 pre_touch = 0;

static u8 pre_key = 0;

u8  key_value = 0;

u8* coor_data = NULL;

s32 input_x = 0;

s32 input_y = 0;

s32 input_w = 0;

s32 id = 0;

s32 i  = 0;

s32 ret = -1;

struct goodix_ts_data *ts = NULL;

dprintk(DEBUG_X_Y_INFO,"===enter %s===\n",__func__);

ts = container_of(work, struct goodix_ts_data, work);

if (ts->enter_update){

return;

}

ret = gtp_i2c_read(ts->client, point_data, 12);

if (ret < 0){

printk("I2C transfererror. errno:%d\n ", ret);

goto exit_work_func;

}

finger = point_data[GTP_ADDR_LENGTH];

if((finger & 0x80) == 0) {

goto exit_work_func;

}

touch_num = finger & 0x0f;

if (touch_num > GTP_MAX_TOUCH) {

goto exit_work_func;

}

if (touch_num > 1) {

u8 buf[8 * GTP_MAX_TOUCH] ={(GTP_READ_COOR_ADDR + 10) >> 8, (GTP_READ_COOR_ADDR + 10) & 0xff};

ret =gtp_i2c_read(ts->client, buf, 2 + 8 * (touch_num - 1));

memcpy(&point_data[12],&buf[2], 8 * (touch_num - 1));

}

#if GTP_HAVE_TOUCH_KEY

key_value = point_data[3 + 8 * touch_num];

if(key_value || pre_key) {

for (i = 0; i <GTP_MAX_KEY_NUM; i++) {

input_report_key(ts->input_dev, touch_key_array[i], key_value &(0x01<<i));

}

touch_num = 0;

pre_touch = 0;

}

#endif

pre_key = key_value;

dprintk(DEBUG_X_Y_INFO, "pre_touch:%02x, finger:%02x.",pre_touch, finger);

#if GTP_ICS_SLOT_REPORT

if (pre_touch || touch_num) {

s32 pos = 0;

u16 touch_index = 0;

coor_data = &point_data[3];

if(touch_num) {

id = coor_data[pos]& 0x0F;

touch_index |=(0x01<<id);

}

dprintk(DEBUG_X_Y_INFO,

"id=%d,touch_index=0x%x, pre_touch=0x%x\n", id, touch_index, pre_touch);

for (i = 0; i <GTP_MAX_TOUCH; i++) {

if (touch_index &(0x01<<i)) {

input_x  = coor_data[pos + 1] | coor_data[pos + 2]<< 8;

input_y  = coor_data[pos + 3] | coor_data[pos + 4]<< 8;

input_w  = coor_data[pos + 5] | coor_data[pos + 6]<< 8;

gtp_touch_down(ts, id, input_x, input_y, input_w);

pre_touch |=0x01 << i;

pos += 8;

id =coor_data[pos] & 0x0F;

touch_index |=(0x01<<id);

}else {// if (pre_touch& (0x01 << i))

gtp_touch_up(ts, i);

pre_touch&= ~(0x01 << i);

}

}

}

#else

if (touch_num ) {

for (i = 0; i < touch_num;i++) {

coor_data =&point_data[i * 8 + 3];

id = coor_data[0] &0x0F;

input_x  = coor_data[1] | coor_data[2] << 8;

input_y  = coor_data[3] | coor_data[4] << 8;

input_w  = coor_data[5] | coor_data[6] << 8;

gtp_touch_down(ts, id,input_x, input_y, input_w);

}

}else if(pre_touch){

dprintk(DEBUG_X_Y_INFO,"Touch Release!");

gtp_touch_up(ts, 0);

}

pre_touch = touch_num;

#endif

input_sync(ts->input_dev);

exit_work_func:

if(!ts->gtp_rawdiff_mode) {

ret =gtp_i2c_write(ts->client, end_cmd, 3);

if (ret < 0) {

printk("I2C writeend_cmd  error!");

}

}

return ;

}

/*******************************************************

Function:

Externalinterrupt service routine.

Input:

irq: interrupt number.

dev_id:private data pointer.

Output:

irqexecute status.

*******************************************************/

irqreturn_t goodix_ts_irq_handler(int irq,void *dev_id)

{

struct goodix_ts_data *ts = (struct goodix_ts_data *)dev_id;

dprintk(DEBUG_INT_INFO,"==========------TS Interrupt-----============\n");

queue_work(goodix_wq, &ts->work);

return 0;

}

/*******************************************************

Function:

Etersleep function.

Input:

ts:privatedata.

Output:

Executiveoutcomes.0--success,non-0--fail.

*******************************************************/

static s8 gtp_enter_sleep(structgoodix_ts_data * ts)

{

s8 ret = -1;

s8 retry = 0;

u8 i2c_control_buf[3] = {(u8)(GTP_REG_SLEEP >> 8),(u8)GTP_REG_SLEEP, 5};

dprintk(DEBUG_SUSPEND, "%s start!\n", __func__);

gtp_set_int_value(0);

msleep(5);

while(retry++ < 5) {

ret =gtp_i2c_write(ts->client, i2c_control_buf, 3);

if (ret > 0) {

dprintk(DEBUG_SUSPEND,"GTP enter sleep!");

return ret;

}

msleep(10);

}

dprintk(DEBUG_SUSPEND, "GTP send sleep cmd failed.");

return ret;

}

/*******************************************************

Function:

Wakeupfrom sleep mode Function.

Input:

ts:  private data.

Output:

Executiveoutcomes.0--success,non-0--fail.

*******************************************************/

static s8 gtp_wakeup_sleep(structgoodix_ts_data * ts)

{

u8 retry = 0;

s8 ret = -1;

gtp_io_init(20);

gtp_set_io_int();

#if GTP_POWER_CTRL_SLEEP

while(retry++ < 5)

{

gtp_reset_guitar(ts->client, 20);

GTP_INFO("GTP wakeup sleep.");

return 1;

}

#else

while(retry++ < 10)

{

#if GTP_GESTURE_WAKEUP

if (DOZE_WAKEUP != doze_status)

{

GTP_INFO("Powerkey wakeup.");

}

else

{

GTP_INFO("Gesture wakeup.");

}

doze_status = DOZE_DISABLED;

gtp_irq_disable(ts);

gtp_reset_guitar(ts->client, 10);

gtp_irq_enable(ts);

#else

gtp_set_int_value(1);

msleep(5);

#endif

ret = gtp_i2c_test(ts->client);

if (ret > 0)

{

GTP_INFO("GTP wakeupsleep.");

#if (!GTP_GESTURE_WAKEUP)

{

gtp_int_sync(25);

#if GTP_ESD_PROTECT

gtp_init_ext_watchdog(ts->client);

#endif

}

#endif

return ret;

}

gtp_reset_guitar(ts->client, 20);

}

#endif

GTP_ERROR("GTP wakeup sleep failed.");

return ret;

}

/*******************************************************

Function:

GTP initializefunction.

Input:

ts:  i2c client private struct.

Output:

Executiveoutcomes.0---succeed.

*******************************************************/

static s32 gtp_init_panel(structgoodix_ts_data *ts)

{

s32 ret = -1;

s32i = 0;

u8 check_sum = 0;

u8 opr_buf[16] = {0};

u8 sensor_id = 0;

u8drv_cfg_version;

u8flash_cfg_version;

u8 send_cfg_buf[] = CTP_CFG_GROUP0;

u8 cfg_info_len = GTP_CONFIG_MIN_LENGTH;

ts->gtp_cfg_len= cfg_info_len;

gtp_int_sync(20);          //先同步一下INT脚才能读到正确的配置信息

memset(config+GTP_ADDR_LENGTH,0, GTP_CONFIG_MAX_LENGTH);

if(gtp_i2c_read(ts->client,config, GTP_CONFIG_MIN_LENGTH+GTP_ADDR_LENGTH) < 0)

{

GTP_DEBUG("readgt9xx config data failed! return.\r\n");

return-1;

}

GTP_DEBUG("readconfig data ok!,as follows:\r\n");

GTP_DEBUG_ARRAY(config+GTP_ADDR_LENGTH,GTP_CONFIG_MIN_LENGTH);                //读出原配置信息,以利恢复_记得将打印出来的配置信息保存

#if GTP_DRIVER_SEND_CFG

/*check firmware */

ret= gtp_i2c_read_dbl_check(ts->client, 0x41E4, opr_buf, 1);

if(SUCCESS == ret)

{

if(opr_buf[0] != 0xBE)

{

ts->fw_error= 1;

GTP_ERROR("Firmwareerror, no config sent!");

return-1;

}

}

#if GTP_CONFIG_MODE        //根据厂家数据表配罿

memcpy(config+GTP_ADDR_LENGTH,send_cfg_buf, ts->gtp_cfg_len);

ret= gtp_i2c_read_dbl_check(ts->client, GTP_REG_CONFIG_DATA, &opr_buf[0],1);//读版本号

if(ret == SUCCESS)

{

GTP_DEBUG("ConfigVersion: 0x%02X; IC Config Version: 0x%02X", \

config[GTP_ADDR_LENGTH],opr_buf[0]);

flash_cfg_version= opr_buf[0];

drv_cfg_version= config[GTP_ADDR_LENGTH];

if(flash_cfg_version < 90 && flash_cfg_version > drv_cfg_version)

{

config[GTP_ADDR_LENGTH]= 0x00;       //版本写入0,强制更新版本为0X41 A版本

}

}

else

{

GTP_ERROR("Failedto get ic config version!No config sent!");

return-1;

}

#endif//GTP_CONFIG_MODE

#if GTP_CUSTOM_CFG

config[RESOLUTION_LOC]     =(u8)GTP_MAX_WIDTH;

config[RESOLUTION_LOC + 1] = (u8)(GTP_MAX_WIDTH>>8);

config[RESOLUTION_LOC + 2] = (u8)GTP_MAX_HEIGHT;

config[RESOLUTION_LOC + 3] = (u8)(GTP_MAX_HEIGHT>>8);

config[RESOLUTION_LOC+ 4] = (u8)GTP_MAX_TOUCH;

config[TRIGGER_LOC] &= 0xfc;

config[TRIGGER_LOC]|= GTP_INT_TRIGGER;

#endif // GTP_CUSTOM_CFG

check_sum = 0;

for (i = GTP_ADDR_LENGTH; i < ts->gtp_cfg_len; i++)

{

check_sum += config[i];

}

config[ts->gtp_cfg_len] = (~check_sum) + 1;

config[ts->gtp_cfg_len+1]= 1;

ret= gtp_send_cfg(ts->client);

if(ret < 0)

{

GTP_ERROR("Sendconfig error.");

}

ts->abs_x_max= (config[RESOLUTION_LOC + 1] << 8) + config[RESOLUTION_LOC];

ts->abs_y_max= (config[RESOLUTION_LOC + 3] << 8) + config[RESOLUTION_LOC + 2];

ts->int_trigger_type= (config[TRIGGER_LOC]) & 0x03;

#if GTP_CONFIG_MODE        //根据厂家数据表配罿

if(flash_cfg_version < 90 && flash_cfg_version > drv_cfg_version)

{

config[GTP_ADDR_LENGTH]= 0x41;       //版本写入0x41 ,唤醒时不会强制更新版本

}

#endif//GTP_CONFIG_MODE

#else // driver not send config

ts->abs_x_max = GTP_MAX_WIDTH;

ts->abs_y_max= GTP_MAX_HEIGHT;

ts->int_trigger_type= GTP_INT_TRIGGER;

#endif // GTP_DRIVER_SEND_CFG

GTP_INFO("X_MAX: %d, Y_MAX: %d, TRIGGER: 0x%02x",ts->abs_x_max,ts->abs_y_max,ts->int_trigger_type);

msleep(10);

return 0;

}

/*******************************************************

Function:

Readgoodix touchscreen version function.

Input:

client:   i2c client struct.

version:addressto store version info

Output:

Executiveoutcomes.0---succeed.

*******************************************************/

s32 gtp_read_version(struct i2c_client*client, u16* version)

{

s32 ret = -1;

u8 buf[8] = {GTP_REG_VERSION >> 8, GTP_REG_VERSION & 0xff};

dprintk(DEBUG_INIT, "%s ---start!.---\n", __func__);

ret = gtp_i2c_read(client, buf, sizeof(buf));

if (ret < 0) {

printk("GTP read versionfailed");

return ret;

}

if (version) {

*version = (buf[7] << 8)| buf[6];

}

if (buf[5] == 0x00) {

printk("IC Version:%c%c%c_%02x%02x", buf[2], buf[3], buf[4], buf[7], buf[6]);

}

else {

printk("IC Version:%c%c%c%c_%02x%02x", buf[2], buf[3], buf[4], buf[5], buf[7], buf[6]);

}

return ret;

}

/*******************************************************

Function:

I2ctest Function.

Input:

client:i2cclient.

Output:

Executiveoutcomes.0--success,non-0--fail.

*******************************************************/

static s8 gtp_i2c_test(struct i2c_client*client)

{

u8 test[3] = {GTP_REG_CONFIG_DATA >> 8, GTP_REG_CONFIG_DATA &0xff};

u8 retry = 0;

s8 ret = -1;

while(retry++ < 2) {

ret = gtp_i2c_read(client,test, 3);

if (ret > 0) {

return ret;

}

printk("GTP i2c testfailed time %d.",retry);

msleep(10);

}

return ret;

}

/*******************************************************

Function:

Requestinput device Function.

Input:

ts:privatedata.

Output:

Executiveoutcomes.0--success,non-0--fail.

*******************************************************/

static s8 gtp_request_input_dev(structgoodix_ts_data *ts)

{

s8 ret = -1;

#if GTP_HAVE_TOUCH_KEY

u8 index = 0;

#endif

ts->input_dev = input_allocate_device();

if (ts->input_dev == NULL) {

GTP_ERROR("Failed toallocate input device.");

return -ENOMEM;

}

ts->input_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) |BIT_MASK(EV_ABS) ;

#if GTP_ICS_SLOT_REPORT

__set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit);

input_mt_init_slots(ts->input_dev, 255);

#else

ts->input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);

#endif

#if GTP_HAVE_TOUCH_KEY

for (index = 0; index < GTP_MAX_KEY_NUM; index++) {

input_set_capability(ts->input_dev,EV_KEY,touch_key_array[index]);

}

#endif

//#if GTP_CHANGE_X2Y

//       GTP_SWAP(ts->abs_x_max, ts->abs_y_max);

//#endif

input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, 0,SCREEN_MAX_X, 0, 0);

input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, 0,SCREEN_MAX_Y, 0, 0);

input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0,0);

input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0,0);

input_set_abs_params(ts->input_dev, ABS_MT_TRACKING_ID, 0, 255, 0,0);

set_bit(INPUT_PROP_DIRECT,ts->input_dev->propbit);

ts->input_dev->name = CTP_NAME;

ts->input_dev->phys = "input/goodix-ts";

ts->input_dev->id.bustype = BUS_I2C;

ts->input_dev->id.vendor = 0xDEAD;

ts->input_dev->id.product = 0xBEEF;

ts->input_dev->id.version = 10427;

ret = input_register_device(ts->input_dev);

if (ret) {

printk("Register %s inputdevice failed", ts->input_dev->name);

return -ENODEV;

}

#ifdef CONFIG_HAS_EARLYSUSPEND

ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;

ts->early_suspend.suspend = goodix_ts_early_suspend;

ts->early_suspend.resume = goodix_ts_late_resume;

register_early_suspend(&ts->early_suspend);

#endif

return 0;

}

/*******************************************************

Function:

Goodixtouchscreen probe function.

Input:

client:   i2c device struct.

id:deviceid.

Output:

Executiveoutcomes. 0---succeed.

*******************************************************/

static int goodix_ts_probe(structi2c_client *client, const struct i2c_device_id *id)

{

s32 ret = -1;

struct goodix_ts_data *ts;

u16 version_info;

dprintk(DEBUG_INIT, "GTP DriverVersion:%s\n",GTP_DRIVER_VERSION);

dprintk(DEBUG_INIT, "GTP Driver build@%s,%s\n",__TIME__,__DATE__);

printk("GTP I2C Address:0x%02x\n", client->addr);

i2c_connect_client = client;

if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {

printk("I2C checkfunctionality failed.\n");

return -ENODEV;

}

ts = kzalloc(sizeof(*ts), GFP_KERNEL);

if (ts == NULL) {

printk("Alloc GFP_KERNELmemory failed.\n");

return -ENOMEM;

}

memset(ts, 0, sizeof(*ts));

INIT_WORK(&ts->work, goodix_ts_work_func);

ts->client = client;

i2c_set_clientdata(client, ts);

//ts->irq_lock = SPIN_LOCK_UNLOCKED;

ts->gtp_rawdiff_mode = 0;

ret = gtp_i2c_test(client);

if (ret < 0){

printk("I2C communicationERROR!\n");

goto exit_device_detect;

}

goodix_resume_wq = create_singlethread_workqueue("goodix_resume");

if (goodix_resume_wq == NULL) {

printk("create goodix_resume_wqfail!\n");

return -ENOMEM;

}

goodix_wq =create_singlethread_workqueue("goodix_wq");

if (!goodix_wq) {

printk(KERN_ALERT "Creat goodix_wqworkqueue failed.\n");

return-ENOMEM;

}

#if GTP_AUTO_UPDATE

ret = gup_init_update_proc(ts);

if (ret < 0) {

printk("Create updatethread error.");

}

#endif

ret = gtp_init_panel(ts);

if (ret < 0) {

printk("GTP init panelfailed.\n");

}

ret = gtp_request_input_dev(ts);

if (ret < 0) {

printk("GTP request inputdev failed\n");

gotoexit_device_detect;

}

ret= gtp_read_version(client, &version_info);

if(ret < 0) {

printk("Readversion failed.");

}

config_info.dev= &(ts->input_dev->dev);

ret = input_request_int(&(config_info.input_type), goodix_ts_irq_handler,CTP_IRQ_MODE,ts);

if (ret) {

printk("Request irqfail!.\n");

}

spin_lock_init(&ts->irq_lock);

#if GTP_CREATE_WR_NODE

init_wr_node(client);

#endif

#if GTP_ESD_PROTECT

INIT_DELAYED_WORK(&gtp_esd_check_work, gtp_esd_check_func);

gtp_esd_check_workqueue = create_workqueue("gtp_esd_check");

queue_delayed_work(gtp_esd_check_workqueue, &gtp_esd_check_work,GTP_ESD_CHECK_CIRCLE);

#endif

dprintk(DEBUG_INIT,"gt9xx probe success!\n");

return 0;

exit_device_detect:

i2c_set_clientdata(client,NULL);

kfree(ts);

returnret;

}

/*******************************************************

Function:

Goodixtouchscreen driver release function.

Input:

client:   i2c device struct.

Output:

Executiveoutcomes. 0---succeed.

*******************************************************/

static int goodix_ts_remove(structi2c_client *client)

{

struct goodix_ts_data *ts = i2c_get_clientdata(client);

dprintk(DEBUG_INIT,"%sstart!\n", __func__);

#ifdef CONFIG_HAS_EARLYSUSPEND

unregister_early_suspend(&ts->early_suspend);

#endif

#if GTP_CREATE_WR_NODE

uninit_wr_node();

#endif

#if GTP_ESD_PROTECT

flush_workqueue(gtp_esd_check_workqueue);

if(gtp_esd_check_workqueue)

destroy_workqueue(gtp_esd_check_workqueue);

#endif

input_free_int(&(config_info.input_type), ts);

flush_workqueue(goodix_wq);

//cancel_work_sync(&goodix_init_work);

cancel_work_sync(&goodix_resume_work);

if(goodix_wq)

destroy_workqueue(goodix_wq);

//destroy_workqueue(goodix_init_wq);

if(goodix_resume_wq)

destroy_workqueue(goodix_resume_wq);

i2c_set_clientdata(ts->client, NULL);

input_unregister_device(ts->input_dev);

kfree(ts);

return 0;

}

static void goodix_resume_events (structwork_struct *work)

{

intret;

struct goodix_ts_data *ts = i2c_get_clientdata(i2c_connect_client);

ret= gtp_wakeup_sleep(ts);

if(ret < 0)

printk("resumepower on failed\n");

gtp_irq_enable(ts);

}

/*******************************************************

Function:

Earlysuspend function.

Input:

h:early_suspendstruct.

Output:

None.

*******************************************************/

#ifdef CONFIG_HAS_EARLYSUSPEND

static void goodix_ts_early_suspend(structearly_suspend *h)

{

struct goodix_ts_data *ts;

s8 ret = -1;

ts = container_of(h, struct goodix_ts_data, early_suspend);

#if GTP_ESD_PROTECT

ts->gtp_is_suspend = 1;

cancel_delayed_work_sync(&gtp_esd_check_work);

#endif

gtp_irq_disable(ts);

cancel_work_sync(&goodix_resume_work);

flush_workqueue(goodix_resume_wq);

ret = cancel_work_sync(&ts->work);

flush_workqueue(goodix_wq);

ret = gtp_enter_sleep(ts);

if (ret < 0) {

printk("GTP early suspendfailed.");

}

}

/*******************************************************

Function:

Lateresume function.

Input:

h:early_suspendstruct.

Output:

None.

*******************************************************/

static void goodix_ts_late_resume(structearly_suspend *h)

{

struct goodix_ts_data *ts;

ts = container_of(h, struct goodix_ts_data, early_suspend);

queue_work(goodix_resume_wq, &goodix_resume_work);//gandy

#if GTP_ESD_PROTECT

ts->gtp_is_suspend = 0;

queue_delayed_work(gtp_esd_check_workqueue, &gtp_esd_check_work,GTP_ESD_CHECK_CIRCLE);

#endif

}

#else

#ifdef CONFIG_PM

static void goodix_ts_suspend(structi2c_client *client, pm_message_t mesg)

{

struct goodix_ts_data *ts;

s8 ret = -1;

ts = i2c_get_clientdata(client);

printk("%s goodix_ts_suspend\n", goodix_ts_name);

#if GTP_ESD_PROTECT

ts->gtp_is_suspend = 1;

cancel_delayed_work_sync(&gtp_esd_check_work);

#endif

ret = input_set_int_enable(&(config_info.input_type), 0);

if (ret < 0)

dprintk(DEBUG_SUSPEND,"%sirq disable failed\n", goodix_ts_name);

cancel_work_sync(&goodix_resume_work);

flush_workqueue(goodix_resume_wq);

ret = cancel_work_sync(&ts->work);

flush_workqueue(goodix_wq);

ret = gtp_enter_sleep(ts);

if (ret < 0) {

printk("GTP suspendfailed.");

}

}

static void goodix_ts_resume(structi2c_client *client)

{

struct goodix_ts_data *ts;

ts = i2c_get_clientdata(client);

printk("%s goodix_ts_resume\n",goodix_ts_name);

queue_work(goodix_resume_wq, &goodix_resume_work);//gandy

#if GTP_ESD_PROTECT

ts->gtp_is_suspend = 0;

queue_delayed_work(gtp_esd_check_workqueue, &gtp_esd_check_work,GTP_ESD_CHECK_CIRCLE);

#endif

}

#endif

#endif

#if GTP_ESD_PROTECT

/*******************************************************

Function:

Initialize external watchdog for esd protect

Input:

client:  i2c device.

Output:

result of i2c write operation.

1: succeed, otherwise: failed

*********************************************************/

s32 gtp_init_ext_watchdog(structi2c_client *client)

{

u8 opr_buffer[4] = {0x80, 0x40, 0xAA, 0xAA};

dprintk(DEBUG_INIT, "Init external watchdog...");

return gtp_i2c_write(client, opr_buffer, 4);

}

/*******************************************************

Function:

Esd protect function.

Added external watchdog by meta, 2013/03/07

Input:

work: delayed work

Output:

None.

*******************************************************/

static void gtp_esd_check_func(structwork_struct *work)

{

s32 i;

s32 ret = -1;

struct goodix_ts_data *ts = NULL;

u8 test[4] = {0x80, 0x40};

dprintk(DEBUG_INIT, "enter %s work!\n", __func__);

ts = i2c_get_clientdata(i2c_connect_client);

if (ts->gtp_is_suspend || ts->enter_update) {

return;

}

for (i = 0; i < 3; i++) {

ret =gtp_i2c_read(ts->client, test, 4);

dprintk(DEBUG_INIT,"0x8040 = 0x%02X, 0x8041 = 0x%02X", test[2], test[3]);

if ((ret < 0)) {

// IC worksabnormally..

continue;

}else {

if ((test[2] == 0xAA)|| (test[3] != 0xAA)) {

// IC works abnormally..

i = 3;

break;

}else {

// IC worksnormally, Write 0x8040 0xAA

test[2] = 0xAA;

gtp_i2c_write(ts->client, test, 3);

break;

}

}

}

if (i >= 3) {

GTP_DEBUG("IC WorkingABNORMALLY, Resetting Guitar...");

//  gtp_reset_guitar(ts->client, 50);

}

if(!ts->gtp_is_suspend) {

queue_delayed_work(gtp_esd_check_workqueue, &gtp_esd_check_work,GTP_ESD_CHECK_CIRCLE);

}

return;

}

#endif

static const struct i2c_device_idgoodix_ts_id[] = {

{ CTP_NAME, 0 },

{ }

};

static struct i2c_driver goodix_ts_driver= {

.class          = I2C_CLASS_HWMON,

.probe          = goodix_ts_probe,

.remove         = goodix_ts_remove,

#ifndef CONFIG_HAS_EARLYSUSPEND

#ifdef CONFIG_PM

.suspend        =goodix_ts_suspend,

.resume         =goodix_ts_resume,

#endif

#endif

.id_table       = goodix_ts_id,

.driver = {

.name   = CTP_NAME,

.owner  = THIS_MODULE,

},

.address_list  = normal_i2c,

};

static int ctp_get_system_config(void)

{

ctp_print_info(config_info,DEBUG_INIT);

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 configerror!\n",__func__);

return 0;

}

return 1;

}

/*******************************************************

Function:

DriverInstall function.

Input:

None.

Output:

ExecutiveOutcomes. 0---succeed.

********************************************************/

static int __devinit goodix_ts_init(void)

{

s32 ret = -1;

dprintk(DEBUG_INIT,"****************************************************************\n");

struct regulator *ldo = regulator_get(NULL, "axp22_ldoio1");

if (input_fetch_sysconfig_para(&(config_info.input_type))) {

printk("%s:ctp_fetch_sysconfig_para err.\n", __func__);

return0;

} else {

printk("%s:gt9xx ctp_fetch_sysconfig_para ok.\n", __func__);

ret= input_init_platform_resource(&(config_info.input_type));

if(0 != ret) {

printk("%s:ctp_ops.init_platform_resourceerr. \n", __func__);

}

}

if(config_info.ctp_used == 0){

printk("*** ctp_used set to 0!\n");

printk("*** if use ctp,please putthe sys_config.fex ctp_used set to 1. \n");

return 0;

}

//关于电压部分是关键

if(IS_ERR(ldo)) {

printk("glsX680get regulator error!! \n");

return-1;

}else {

regulator_set_voltage(ldo,3300000, 3300000);

if(!regulator_is_enabled(ldo)){

regulator_enable(ldo);

}

regulator_put(ldo);

}

if(!ctp_get_system_config()){

printk("%s:read configfail!\n",__func__);

return ret;

}

input_set_power_enable(&(config_info.input_type),1);

msleep(10);

sunxi_gpio_to_name(CTP_IRQ_NUMBER,irq_pin_name);

gtp_io_init(20);

goodix_ts_driver.detect= ctp_detect;

ret = i2c_add_driver(&goodix_ts_driver);

printk("%s: gt9xx init over!.\n", __func__);

dprintk(DEBUG_INIT,"****************************************************************\n");

return ret;

}

/*******************************************************

Function:

Driveruninstall function.

Input:

None.

Output:

ExecutiveOutcomes. 0---succeed.

********************************************************/

static void __exit goodix_ts_exit(void)

{

printk("GTP driver exited.\n");

i2c_del_driver(&goodix_ts_driver);

input_free_platform_resource(&(config_info.input_type));

}

late_initcall(goodix_ts_init);

module_exit(goodix_ts_exit);

MODULE_DESCRIPTION("GTP SeriesDriver");

MODULE_LICENSE("GPL");

四.      编译打包

回到目录:/home/yygyickl/A33/dragonboard

./build.sh  重新编译

./build.sh pack_debug      打包debug 固件

五.      烧到开发板,进入 校准程序后,触摸正常。

全志A33之添加电容触摸GT911驱动相关推荐

  1. WT32-SC01是ESP32驱动3.5彩屏开发板方案适合用arduino方式开发吗?因为需要彩屏和电容触摸的驱动的

    ESP32驱动3.5寸彩屏开发板方案因为带有彩屏和电容触摸的驱动,能否用arduino方式开发,这是很多熟悉arduino开发的技术人员关心的问题. 目前启明云端推出的http://esp32.8ms ...

  2. hal编程 gt911 触摸芯片驱动 ( 枚举 结构体 熟用)( 安富莱 f429 4.3寸电容屏 )

    使用板子类型以及屏幕类型 本文使用的是安富莱的板子stm32f429, 屏幕是TR433C1的4.3寸TFT显示屏, 480*272 RGB接口, 电容触摸 . I2C I2C简介.原理.时序请看这篇 ...

  3. a33 linux 硬解码_全志A33 linux led驱动编程(附实测参考代码)

    开发平台 开发平台 * 芯灵思SinlinxA33开发板 嵌入式linux 开发板交流 QQ:641395230 #实验原理 在芯灵思开发板上,没有led灯模块,只能通过引脚电平观察: 这里我选择LS ...

  4. 全志A33驱动开发 之 LED操作

    全志A33驱动开发 之 LED操作 一.整体说明 二.注意事项 三.实现led驱动 1.源文件 2.Makefile文件 四.实现测试的应用程序 五.原理图 一.整体说明   本次使用的开发板是锐尔威 ...

  5. EMWIN电容触摸Touch步骤及注意事项

    文章目录 1.添加触摸IC驱动 2.使能EMWIN触摸 GUIConf.h 3.添加EMWIN GUI_X_Touch_Analog.c文件 4.定时调用GUI_TOUCH_Exec 5 GT911移 ...

  6. 20150906全志a33上调通rtl8188eus的过程(sina33)

    20150906全志a33上调通rtl8188eus的过程(sina33) 使用SINA33的开发板,测试USB接口的WIFI:rtl8188eus. rtl8188eus直接接到SINA33开发板的 ...

  7. 基于全志A33开发板linux系统移植学习记录(Boot0)

    基于全志A33开发板linux系统移植学习记录 第一章 Boot0基于ARMGCC的编译与修改 文章目录 基于全志A33开发板linux系统移植学习记录 前言 一.全志A33简介以及上电引导流程 二. ...

  8. ESP32 开发笔记(三)源码示例 24_XPT2046_Touch_Test 电阻触摸XPT2046驱动测试触摸校正

    开发板购买链接 https://item.taobao.com/item.htm?spm=a2oq0.12575281.0.0.50111deb2Ij1As&ft=t&id=62636 ...

  9. 【全志T113-S3_100ask】15-1 内核5.4驱动spi屏幕——ILI9341

    [全志T113-S3_100ask]15-1 内核5.4驱动spi屏幕--ILI9341 背景 (一)spi设备树 1.修改设备树 2.完善设备树 (二)使能内核 (三)兼容性修改 (四)测试 背景 ...

最新文章

  1. JVM结构、GC工作机制详解
  2. C++ 基本数据类型
  3. 怎么批量抠复杂的图_怎么用手机修图,抠图、拼图,证件照制作?
  4. servlet的重定向错误
  5. python吧_Python | 初识Python程序设计
  6. 80211 发送速率选择算法分析
  7. 鸿蒙系统笔记本价格,鸿蒙系统手机华为P50将明年3月发售,华为P40价格骤降至冰点...
  8. 不安装cudnn可不可以_关于CUDA和cuDNN的安装
  9. php 权限规范,项目人员权限验证
  10. 5月20日,GaussDB将有大事发生
  11. iphone字体_朋友圈换个花样字体,发个朋友圈也高级过人
  12. 练手|常见近30种NLP任务的练手项目
  13. Attention机制的小理解
  14. Soem配置汇川SV660N
  15. 运放输入偏置电流方向_运算放大器输入偏置电流的两种测试方法研究
  16. 如何认识会计科目,看懂财务报表?
  17. 组成原理 - 网卡与HBA卡的区别
  18. sox源码分析:sox_find_effect()
  19. 【100%通过率】华为OD机试真题 Python 实现【士兵过河】【2022.11 Q4 新题】
  20. idea火箭_火箭的大脑

热门文章

  1. java 流程控制语句
  2. mpvue 模板_使用mpvue创建项目以及总结
  3. 电脑网速被限制的查看及解决
  4. Tor 技术和 Torpark 浏览器
  5. 《论文写作》—— 心得体会
  6. [COCI2017-2018#5] Olivander
  7. spark数据分析之ip归属地查询
  8. RocketMQ常用命令使用示例及说明
  9. 恢复浏览器收藏夹数据
  10. 上海亚商投顾:沪指冲高回落 纺织服装股午后集体走强