MTK平台添加防止误触代码

ltr559_old:

 

#include <linux/interrupt.h> #include <linux/i2c.h> #include <linux/slab.h> #include <linux/irq.h> #include <linux/miscdevice.h> #include <asm/uaccess.h> #include <linux/delay.h> #include <linux/input.h> #include <linux/workqueue.h> #include <linux/kobject.h> #include <linux/earlysuspend.h> #include <linux/platform_device.h> #include <asm/atomic.h>

#include <mach/mt_typedefs.h> #include <mach/mt_gpio.h> #include <mach/mt_pm_ldo.h> #include <linux/hwmsensor.h> #include <linux/hwmsen_dev.h> #include <linux/sensors_io.h> #include <asm/io.h> #include <cust_eint.h> #include <cust_alsps.h> #include <linux/hwmsen_helper.h> #include "ltr559.h"

#include <linux/earlysuspend.h> #include <linux/wakelock.h> #include <linux/sched.h> #include <alsps.h> #include <linux/mutex.h>

#undef CUSTOM_KERNEL_SENSORHUB #ifdef CUSTOM_KERNEL_SENSORHUB #include <SCP_sensorHub.h> #endif

#define POWER_NONE_MACRO MT65XX_POWER_NONE #define GN_MTK_BSP_PS_DYNAMIC_CALI

/******************************************************************************  * configuration *******************************************************************************/ /*----------------------------------------------------------------------------*/

#define LTR559_DEV_NAME   "LTR_559ALS"

/*----------------------------------------------------------------------------*/ #define APS_TAG                  "[ALS/PS] " #define APS_FUN(f)               printk(KERN_ERR APS_TAG"%s\n", __FUNCTION__) #define APS_ERR(fmt, args...)    printk(KERN_ERR  APS_TAG"%s %d : "fmt, __FUNCTION__, __LINE__, ##args)

#define APS_ERR_ST(f)    printk(KERN_ERR  APS_TAG"%s %d : ", __FUNCTION__, __LINE__)

#define APS_LOG(fmt, args...)    printk(KERN_ERR APS_TAG fmt, ##args) #define APS_DBG(fmt, args...)    printk(KERN_ERR APS_TAG fmt, ##args)                 /******************************************************************************  * extern functions *******************************************************************************/

extern void mt_eint_mask(unsigned int eint_num); extern void mt_eint_unmask(unsigned int eint_num); extern void mt_eint_set_hw_debounce(unsigned int eint_num, unsigned int ms); extern void mt_eint_set_polarity(unsigned int eint_num, unsigned int pol); extern unsigned int mt_eint_set_sens(unsigned int eint_num, unsigned int sens); extern void mt_eint_registration(unsigned int eint_num, unsigned int flow, void (EINT_FUNC_PTR)(void), unsigned int is_auto_umask); extern void mt_eint_print_status(void); /*----------------------------------------------------------------------------*/

static struct i2c_client *ltr559_i2c_client = NULL;

/*----------------------------------------------------------------------------*/ static const struct i2c_device_id ltr559_i2c_id[] = {{LTR559_DEV_NAME,0},{}}; /*the adapter id & i2c address will be available in customization*/ static struct i2c_board_info __initdata i2c_ltr559={ I2C_BOARD_INFO("LTR_559ALS", 0x23)};

//static unsigned short ltr559_force[] = {0x00, 0x46, I2C_CLIENT_END, I2C_CLIENT_END}; //static const unsigned short *const ltr559_forces[] = { ltr559_force, NULL }; //static struct i2c_client_address_data ltr559_addr_data = { .forces = ltr559_forces,}; /*----------------------------------------------------------------------------*/ static int ltr559_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id); static int ltr559_i2c_remove(struct i2c_client *client); static int ltr559_i2c_detect(struct i2c_client *client, int kind, struct i2c_board_info *info); /*----------------------------------------------------------------------------*/ static int ltr559_i2c_suspend(struct i2c_client *client, pm_message_t msg); static int ltr559_i2c_resume(struct i2c_client *client); static int ltr559_init_device(void);

static int ltr559_ps_enable(int gainrange); static int dynamic_calibrate=0;

static int ps_trigger_high = 800;  static int ps_trigger_low = 760;

static int ps_gainrange; static int als_gainrange;

static int final_prox_val , prox_val; static int final_lux_val;

/*----------------------------------------------------------------------------*/ static DEFINE_MUTEX(read_lock);

/*----------------------------------------------------------------------------*/ static int ltr559_als_read(int gainrange); static int ltr559_ps_read(void);

/*----------------------------------------------------------------------------*/

typedef enum {     CMC_BIT_ALS    = 1,     CMC_BIT_PS     = 2, } CMC_BIT;

/*----------------------------------------------------------------------------*/ struct ltr559_i2c_addr {    /*define a series of i2c slave address*/     u8  write_addr;      u8  ps_thd;     /*PS INT threshold*/ };

/*----------------------------------------------------------------------------*/

struct ltr559_priv {     struct alsps_hw  *hw;     struct i2c_client *client;     struct work_struct  eint_work;     struct mutex lock;  /*i2c address group*/     struct ltr559_i2c_addr  addr;

     /*misc*/     u16      als_modulus;     atomic_t    i2c_retry;     atomic_t    als_debounce;   /*debounce time after enabling als*/     atomic_t    als_deb_on;     /*indicates if the debounce is on*/     atomic_t    als_deb_end;    /*the jiffies representing the end of debounce*/     atomic_t    ps_mask;        /*mask ps: always return far away*/     atomic_t    ps_debounce;    /*debounce time after enabling ps*/     atomic_t    ps_deb_on;      /*indicates if the debounce is on*/     atomic_t    ps_deb_end;     /*the jiffies representing the end of debounce*/     atomic_t    ps_suspend;     atomic_t    als_suspend;

    /*data*/     u16         als;     u16          ps;     u8          _align;     u16         als_level_num;     u16         als_value_num;     u32         als_level[C_CUST_ALS_LEVEL-1];     u32         als_value[C_CUST_ALS_LEVEL];

    atomic_t    als_cmd_val;    /*the cmd value can't be read, stored in ram*/     atomic_t    ps_cmd_val;     /*the cmd value can't be read, stored in ram*/     atomic_t    ps_thd_val;     /*the cmd value can't be read, stored in ram*/  atomic_t    ps_thd_val_high;     /*the cmd value can't be read, stored in ram*/  atomic_t    ps_thd_val_low;     /*the cmd value can't be read, stored in ram*/     ulong       enable;         /*enable mask*/     ulong       pending_intr;   /*pending interrupt*/

    /*early suspend*/ #if defined(CONFIG_HAS_EARLYSUSPEND)     struct early_suspend    early_drv; #endif     };

 struct PS_CALI_DATA_STRUCT {     int close;     int far_away;     int valid; } ;

static struct PS_CALI_DATA_STRUCT ps_cali={0,0,0}; static int intr_flag_value = 0;

static struct ltr559_priv *ltr559_obj = NULL; static struct platform_driver ltr559_alsps_driver;

/*----------------------------------------------------------------------------*/ static struct i2c_driver ltr559_i2c_driver = {   .probe      = ltr559_i2c_probe,  .remove     = ltr559_i2c_remove,  .detect     = ltr559_i2c_detect,  .suspend    = ltr559_i2c_suspend,  .resume     = ltr559_i2c_resume,  .id_table   = ltr559_i2c_id,  //.address_data = &ltr559_addr_data,  .driver = {   //.owner          = THIS_MODULE,   .name           = LTR559_DEV_NAME,  }, };

/*  * #########  * ## I2C ##  * #########  */

// I2C Read static int ltr559_i2c_read_reg(u8 regnum) {     u8 buffer[1],reg_value[1];  int res = 0;  mutex_lock(&read_lock);    buffer[0]= regnum;  res = i2c_master_send(ltr559_obj->client, buffer, 0x1);  if(res <= 0) {         APS_ERR("read reg send res = %d\n",res);   return res;  }  res = i2c_master_recv(ltr559_obj->client, reg_value, 0x1);  if(res <= 0)  {   APS_ERR("read reg recv res = %d\n",res);   return res;  }  mutex_unlock(&read_lock);  return reg_value[0]; }

// I2C Write static int ltr559_i2c_write_reg(u8 regnum, u8 value) {  u8 databuf[2];     int res = 0;     databuf[0] = regnum;    databuf[1] = value;  res = i2c_master_send(ltr559_obj->client, databuf, 0x2);

 if (res < 0)   {    APS_ERR("wirte reg send res = %d\n",res);       return res;   }     else   return 0; }

/*----------------------------------------------------------------------------*/ #ifdef GN_MTK_BSP_PS_DYNAMIC_CALI static ssize_t ltr559_dynamic_calibrate(void)    {                      int ret=0;  int i=0;  int data;  int data_total=0;  ssize_t len = 0;  int noise = 0;  int count = 5;  int max = 0;  struct ltr559_priv *obj = ltr559_obj;  if(!ltr559_obj)  {    APS_ERR("ltr559_obj is null!!\n");   //len = sprintf(buf, "ltr559_obj is null\n");   return -1;  }

 // wait for register to be stable  msleep(15);

 for (i = 0; i < count; i++) {   // wait for ps value be stable      msleep(15);      data=ltr559_ps_read();   if (data < 0) {    i--;    continue;   }        if(data & 0x8000){    noise = 0;    break;   }else{    noise=data;   }       data_total+=data;

  if (max++ > 100) {    //len = sprintf(buf,"adjust fail\n");    return len;   }  }

   noise=data_total/count;

 dynamic_calibrate = noise;  if(noise < 100){

   atomic_set(&obj->ps_thd_val_high,  noise+80);//wangxiqiang    atomic_set(&obj->ps_thd_val_low, noise+60);  }else if(noise < 200){    atomic_set(&obj->ps_thd_val_high,  noise+100);    atomic_set(&obj->ps_thd_val_low, noise+80);  }else if(noise < 300){    atomic_set(&obj->ps_thd_val_high,  noise+100);    atomic_set(&obj->ps_thd_val_low, noise+80);  }else if(noise < 400){    atomic_set(&obj->ps_thd_val_high,  noise+100);    atomic_set(&obj->ps_thd_val_low, noise+80);  }else if(noise < 600){    atomic_set(&obj->ps_thd_val_high,  noise+180);    atomic_set(&obj->ps_thd_val_low, noise+90);  }else if(noise < 1000){   atomic_set(&obj->ps_thd_val_high,  noise+300);   atomic_set(&obj->ps_thd_val_low, noise+180);   }else if(noise < 1250){    atomic_set(&obj->ps_thd_val_high,  noise+400);    atomic_set(&obj->ps_thd_val_low, noise+300);  }  else{    atomic_set(&obj->ps_thd_val_high,  1300);    atomic_set(&obj->ps_thd_val_low, 1000);    //isadjust = 0;   printk(KERN_ERR "ltr558 the proximity sensor structure is error\n");  }    //  int ps_thd_val_low, ps_thd_val_high ;    ps_thd_val_low = atomic_read(&obj->ps_thd_val_low);  ps_thd_val_high = atomic_read(&obj->ps_thd_val_high);

 return 0; } #endif

/*----------------------------------------------------------------------------*/ static ssize_t ltr559_show_als(struct device_driver *ddri, char *buf) {  int res;  u8 dat = 0;    if(!ltr559_obj)  {   APS_ERR("ltr559_obj is null!!\n");   return 0;  }  res = ltr559_als_read(als_gainrange);     return snprintf(buf, PAGE_SIZE, "0x%04X\n", res);      } /*----------------------------------------------------------------------------*/ static ssize_t ltr559_show_ps(struct device_driver *ddri, char *buf) {  int  res;  if(!ltr559_obj)  {   APS_ERR("ltr559_obj is null!!\n");   return 0;  }  res = ltr559_ps_read();     return snprintf(buf, PAGE_SIZE, "0x%04X\n", res);     } /*----------------------------------------------------------------------------*/

/*----------------------------------------------------------------------------*/ static ssize_t ltr559_show_status(struct device_driver *ddri, char *buf) {  ssize_t len = 0;    if(!ltr559_obj)  {   APS_ERR("ltr559_obj is null!!\n");   return 0;  }    if(ltr559_obj->hw)  {     len += snprintf(buf+len, PAGE_SIZE-len, "CUST: %d, (%d %d)\n",    ltr559_obj->hw->i2c_num, ltr559_obj->hw->power_id, ltr559_obj->hw->power_vol);     }  else  {   len += snprintf(buf+len, PAGE_SIZE-len, "CUST: NULL\n");  }

 len += snprintf(buf+len, PAGE_SIZE-len, "MISC: %d %d\n", atomic_read(&ltr559_obj->als_suspend), atomic_read(&ltr559_obj->ps_suspend));

 return len; }

/*----------------------------------------------------------------------------*/ static ssize_t ltr559_store_status(struct device_driver *ddri, char *buf, size_t count) {  int status1,ret;  if(!ltr559_obj)  {   APS_ERR("ltr559_obj is null!!\n");   return 0;  }    if(1 == sscanf(buf, "%d ", &status1))  {      ret=ltr559_ps_enable(ps_gainrange);   APS_DBG("iret= %d, ps_gainrange = %d\n", ret, ps_gainrange);  }  else  {   APS_DBG("invalid content: '%s', length = %ld\n", buf, count);  }  return count;    }

/*----------------------------------------------------------------------------*/ static ssize_t ltr559_show_reg(struct device_driver *ddri, char *buf, size_t count) {  int i,len=0;  int reg[]={0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,   0x8d,0x8e,0x8f,0x90,0x91,0x92,0x93,0x94,0x95,0x97,0x98,0x99,0x9a,0x9e};  for(i=0;i<27;i++)   {   len += snprintf(buf+len, PAGE_SIZE-len, "reg:0x%04X value: 0x%04X\n", reg[i],ltr559_i2c_read_reg(reg[i])); 

     }  return len; } /*----------------------------------------------------------------------------*/ static ssize_t ltr559_store_reg(struct device_driver *ddri, char *buf, size_t count) {  int ret,value;  u32 reg;  if(!ltr559_obj)  {   APS_ERR("ltr559_obj is null!!\n");   return 0;  }    if(2 == sscanf(buf, "%x %x ", &reg,&value))  {   APS_DBG("before write reg: %x, reg_value = %x  write value=%x\n", reg,ltr559_i2c_read_reg(reg),value);      ret=ltr559_i2c_write_reg(reg,value);   APS_DBG("after write reg: %x, reg_value = %x\n", reg,ltr559_i2c_read_reg(reg));  }  else  {   APS_DBG("invalid content: '%s', length = %ld\n", buf, count);  }  return count;    }

/*----------------------------------------------------------------------------*/ static DRIVER_ATTR(als,     S_IWUSR | S_IRUGO, ltr559_show_als,   NULL); static DRIVER_ATTR(ps,      S_IWUSR | S_IRUGO, ltr559_show_ps,    NULL); //static DRIVER_ATTR(config,  S_IWUSR | S_IRUGO, ltr559_show_config,ltr559_store_config); //static DRIVER_ATTR(alslv,   S_IWUSR | S_IRUGO, ltr559_show_alslv, ltr559_store_alslv); //static DRIVER_ATTR(alsval,  S_IWUSR | S_IRUGO, ltr559_show_alsval,ltr559_store_alsval); //static DRIVER_ATTR(trace,   S_IWUSR | S_IRUGO,ltr559_show_trace, ltr559_store_trace); static DRIVER_ATTR(status,  S_IWUSR | S_IRUGO, ltr559_show_status,  ltr559_store_status); static DRIVER_ATTR(reg,     S_IWUSR | S_IRUGO, ltr559_show_reg,   ltr559_store_reg); //static DRIVER_ATTR(i2c,     S_IWUSR | S_IRUGO, ltr559_show_i2c,   ltr559_store_i2c); /*----------------------------------------------------------------------------*/ static struct driver_attribute *ltr559_attr_list[] = {     &driver_attr_als,     &driver_attr_ps,       // &driver_attr_trace,        /*trace log*/    // &driver_attr_config,    // &driver_attr_alslv,    //&driver_attr_alsval,     &driver_attr_status,    //&driver_attr_i2c,     &driver_attr_reg, }; /*----------------------------------------------------------------------------*/ static int ltr559_create_attr(struct driver_attribute *driver) {  int idx, err = 0;  int num = (int)(sizeof(ltr559_attr_list)/sizeof(ltr559_attr_list[0]));

 if (driver == NULL)  {   return -EINVAL;  }

 for(idx = 0; idx < num; idx++)  {   if(err = driver_create_file(driver, ltr559_attr_list[idx]))   {               APS_ERR("driver_create_file (%s) = %d\n", ltr559_attr_list[idx]->attr.name, err);    break;   }  }     return err; } /*----------------------------------------------------------------------------*/  static int ltr559_delete_attr(struct device_driver *driver)  {  int idx ,err = 0;  int num = (int)(sizeof(ltr559_attr_list)/sizeof(ltr559_attr_list[0]));

 if (!driver)  return -EINVAL;

 for (idx = 0; idx < num; idx++)  {   driver_remove_file(driver, ltr559_attr_list[idx]);  }    return err; }

/*----------------------------------------------------------------------------*/

/*  * ###############  * ## PS CONFIG ##  * ###############

 */

static int ltr559_ps_set_thres() {  APS_FUN();

 int res;  u8 databuf[2];     struct i2c_client *client = ltr559_obj->client;   struct ltr559_priv *obj = ltr559_obj;   APS_DBG("ps_cali.valid: %d\n", ps_cali.valid);  if(1 == ps_cali.valid)  {   databuf[0] = LTR559_PS_THRES_LOW_0;   databuf[1] = (u8)(ps_cali.far_away & 0x00FF);   res = i2c_master_send(client, databuf, 0x2);   if(res <= 0)   {    goto EXIT_ERR;    return ltr559_ERR_I2C;   }   databuf[0] = LTR559_PS_THRES_LOW_1;   databuf[1] = (u8)((ps_cali.far_away & 0xFF00) >> 8);   res = i2c_master_send(client, databuf, 0x2);   if(res <= 0)   {    goto EXIT_ERR;    return ltr559_ERR_I2C;   }   databuf[0] = LTR559_PS_THRES_UP_0;    databuf[1] = (u8)(ps_cali.close & 0x00FF);   res = i2c_master_send(client, databuf, 0x2);   if(res <= 0)   {    goto EXIT_ERR;    return ltr559_ERR_I2C;   }   databuf[0] = LTR559_PS_THRES_UP_1;    databuf[1] = (u8)((ps_cali.close & 0xFF00) >> 8);;   res = i2c_master_send(client, databuf, 0x2);   if(res <= 0)   {    goto EXIT_ERR;    return ltr559_ERR_I2C;   }  }  else  {   databuf[0] = LTR559_PS_THRES_LOW_0;   databuf[1] = (u8)((atomic_read(&obj->ps_thd_val_low)) & 0x00FF);   res = i2c_master_send(client, databuf, 0x2);   if(res <= 0)   {    goto EXIT_ERR;    return ltr559_ERR_I2C;   }   databuf[0] = LTR559_PS_THRES_LOW_1;   databuf[1] = (u8)((atomic_read(&obj->ps_thd_val_low )>> 8) & 0x00FF);      res = i2c_master_send(client, databuf, 0x2);   if(res <= 0)   {    goto EXIT_ERR;    return ltr559_ERR_I2C;   }   databuf[0] = LTR559_PS_THRES_UP_0;    databuf[1] = (u8)((atomic_read(&obj->ps_thd_val_high)) & 0x00FF);   res = i2c_master_send(client, databuf, 0x2);   if(res <= 0)   {    goto EXIT_ERR;    return ltr559_ERR_I2C;   }   databuf[0] = LTR559_PS_THRES_UP_1;    databuf[1] = (u8)((atomic_read(&obj->ps_thd_val_high) >> 8) & 0x00FF);   res = i2c_master_send(client, databuf, 0x2);   if(res <= 0)   {    goto EXIT_ERR;    return ltr559_ERR_I2C;   }    }

 res = 0;  return res;    EXIT_ERR:  APS_ERR("set thres: %d\n", res);  return res;

}

static int ltr559_ps_enable(int gainrange) {  struct i2c_client *client = ltr559_obj->client;  struct ltr559_priv *obj = ltr559_obj;  u8 databuf[2];   int res;

 int data;  hwm_sensor_data sensor_data; 

 int error;  int setgain;     APS_LOG("ltr559_ps_enable() ...start!\n");  gainrange = PS_RANGE16;  switch (gainrange) {   case PS_RANGE16:    setgain = MODE_PS_ON_Gain16;    break;

  case PS_RANGE32:    setgain = MODE_PS_ON_Gain32;    break;

  case PS_RANGE64:    setgain = MODE_PS_ON_Gain64;    break;

  default:    setgain = MODE_PS_ON_Gain16;    break;  }

 APS_LOG("LTR559_PS setgain = %d!\n",setgain);

 error = ltr559_i2c_write_reg(LTR559_PS_CONTR, setgain);  if(error<0)  {      APS_LOG("ltr559_ps_enable() error1\n");      return error;  }       //wisky-lxh@20150108  res = ltr559_init_device();  if (res < 0)  {     APS_ERR("ltr559_init_devicet: %d\n", res);   return res;  }  //end-wisky-lxh

     /* ===============   * ** IMPORTANT **   * ===============   * Other settings like timing and threshold to be set here, if required.    * Not set and kept as device default for now.    */

 data = ltr559_i2c_read_reg(LTR559_PS_CONTR);    #ifdef GN_MTK_BSP_PS_DYNAMIC_CALI  //wangxiqiang  if (data & 0x02) {

  if(0 == obj->hw->polling_mode_ps){    mt_eint_mask(CUST_EINT_ALS_NUM);   }      if (ltr559_dynamic_calibrate() < 0)    return -1;  }  #endif 

 /*for interrup work mode support -- by liaoxl.lenovo 12.08.2011*/   if(0 == obj->hw->polling_mode_ps)   {  

   ltr559_ps_set_thres();

   #if 1    databuf[0] = LTR559_INTERRUPT;     databuf[1] = 0x01;    res = i2c_master_send(client, databuf, 0x2);    if(res <= 0)    {     goto EXIT_ERR;     return ltr559_ERR_I2C;    }        databuf[0] = LTR559_INTERRUPT_PERSIST;     databuf[1] = 0x20;    res = i2c_master_send(client, databuf, 0x2);    if(res <= 0)    {     goto EXIT_ERR;     return ltr559_ERR_I2C;    }    mt_eint_unmask(CUST_EINT_ALS_NUM);       #endif     }     APS_LOG("ltr559_ps_enable ...OK!\n");

    return error;

 EXIT_ERR:  APS_ERR("set thres: %d\n", res);  return res; }

// Put PS into Standby mode static int ltr559_ps_disable(void) {  int error;  struct ltr559_priv *obj = ltr559_obj;     error = ltr559_i2c_write_reg(LTR559_PS_CONTR, MODE_PS_StdBy);  if(error<0)       APS_LOG("ltr559_ps_disable ...ERROR\n");   else         APS_LOG("ltr559_ps_disable ...OK\n");

 if(0 == obj->hw->polling_mode_ps)  {      cancel_work_sync(&obj->eint_work);   mt_eint_mask(CUST_EINT_ALS_NUM);  }    return error; }

static int ltr559_ps_read(void) {  int psval_lo, psval_hi, psdata;

 psval_lo = ltr559_i2c_read_reg(LTR559_PS_DATA_0);  APS_DBG("ps_rawdata_psval_lo = %d\n", psval_lo);  if (psval_lo < 0){           APS_DBG("psval_lo error\n");   psdata = psval_lo;   goto out;  }  psval_hi = ltr559_i2c_read_reg(LTR559_PS_DATA_1);     APS_DBG("ps_rawdata_psval_hi = %d\n", psval_hi);

 if (psval_hi < 0){      APS_DBG("psval_hi error\n");   psdata = psval_hi;   goto out;  }    psdata = ((psval_hi & 7)* 256) + psval_lo;     //psdata = ((psval_hi&0x7)<<8) + psval_lo;     APS_DBG("ps_rawdata = %d\n", psdata);

 prox_val = psdata;      out:  final_prox_val = psdata;      return psdata; }

/*  * ################  * ## ALS CONFIG ##  * ################  */

static int ltr559_als_enable(int gainrange) {  int error;  int alsval_ch1_lo,alsval_ch1_hi,alsval_ch1,alsval_ch0_lo,alsval_ch0_hi,alsval_ch0;  gainrange = ALS_RANGE_1300;  APS_LOG("gainrange = %d\n",gainrange);  switch (gainrange)  {   case ALS_RANGE_64K:    error = ltr559_i2c_write_reg(LTR559_ALS_CONTR, MODE_ALS_ON_Range1);    break;

  case ALS_RANGE_32K:    error = ltr559_i2c_write_reg(LTR559_ALS_CONTR, MODE_ALS_ON_Range2);    break;

  case ALS_RANGE_16K:    error = ltr559_i2c_write_reg(LTR559_ALS_CONTR, MODE_ALS_ON_Range3);    break;       case ALS_RANGE_8K:    error = ltr559_i2c_write_reg(LTR559_ALS_CONTR, MODE_ALS_ON_Range4);    break;       case ALS_RANGE_1300:    error = ltr559_i2c_write_reg(LTR559_ALS_CONTR, MODE_ALS_ON_Range5);    break;

  case ALS_RANGE_600:    error = ltr559_i2c_write_reg(LTR559_ALS_CONTR, MODE_ALS_ON_Range6);    break;       default:    error = ltr559_i2c_write_reg(LTR559_ALS_CONTR, MODE_ALS_ON_Range1);       APS_ERR("proxmy sensor gainrange %d!\n", gainrange);    break;  }    ltr559_i2c_read_reg(LTR559_ALS_CONTR);

 mdelay(WAKEUP_DELAY);

 alsval_ch1_lo = ltr559_i2c_read_reg(LTR559_ALS_DATA_CH1_0);  alsval_ch1_hi = ltr559_i2c_read_reg(LTR559_ALS_DATA_CH1_1);  alsval_ch1 = (alsval_ch1_hi * 256) + alsval_ch1_lo;    APS_DBG("enable alsval_ch1_lo = %d,alsval_ch1_hi=%d,alsval_ch1=%d\n",alsval_ch1_lo,alsval_ch1_hi,alsval_ch1);  alsval_ch0_lo = ltr559_i2c_read_reg(LTR559_ALS_DATA_CH0_0);  alsval_ch0_hi = ltr559_i2c_read_reg(LTR559_ALS_DATA_CH0_1);  alsval_ch0 = (alsval_ch0_hi * 256) + alsval_ch0_lo;  APS_DBG("enable alsval_ch0_lo = %d,alsval_ch0_hi=%d,alsval_ch0=%d\n",alsval_ch0_lo,alsval_ch0_hi,alsval_ch0);

  if(error<0)       APS_LOG("ltr559_als_enable ...ERROR\n");   else         APS_LOG("ltr559_als_enable ...OK\n");          return error; }

// Put ALS into Standby mode static int ltr559_als_disable(void) {  int error;  error = ltr559_i2c_write_reg(LTR559_ALS_CONTR, MODE_ALS_StdBy);  if(error<0)       APS_LOG("ltr559_als_disable ...ERROR\n");   else         APS_LOG("ltr559_als_disable ...OK\n");  return error; }

static int ltr559_als_read(int gainrange) {  int alsval_ch0_lo, alsval_ch0_hi, alsval_ch0;  int alsval_ch1_lo, alsval_ch1_hi, alsval_ch1;  int  luxdata_int = -1;  int ratio;  int als_zero_try=0;

als_data_try:

 alsval_ch1_lo = ltr559_i2c_read_reg(LTR559_ALS_DATA_CH1_0);  alsval_ch1_hi = ltr559_i2c_read_reg(LTR559_ALS_DATA_CH1_1);  alsval_ch1 = (alsval_ch1_hi * 256) + alsval_ch1_lo;    APS_DBG("alsval_ch1_lo = %d,alsval_ch1_hi=%d,alsval_ch1=%d\n",alsval_ch1_lo,alsval_ch1_hi,alsval_ch1);  alsval_ch0_lo = ltr559_i2c_read_reg(LTR559_ALS_DATA_CH0_0);  alsval_ch0_hi = ltr559_i2c_read_reg(LTR559_ALS_DATA_CH0_1);  alsval_ch0 = (alsval_ch0_hi * 256) + alsval_ch0_lo;  APS_DBG("alsval_ch0_lo = %d,alsval_ch0_hi=%d,alsval_ch0=%d\n",alsval_ch0_lo,alsval_ch0_hi,alsval_ch0);

    if((alsval_ch1==0)||(alsval_ch0==0))     {      ratio=100;     }else{  ratio = (alsval_ch1*100) /(alsval_ch0+alsval_ch1);     }   APS_DBG("ratio = %d  gainrange = %d\n",ratio,gainrange);  if (ratio < 45){   luxdata_int = (((17743 * alsval_ch0)+(11059 * alsval_ch1)))/10000;  }  else if ((ratio < 64) && (ratio >= 45)){   luxdata_int = (((42785 * alsval_ch0)-(19548 * alsval_ch1)))/10000;  }  else if ((ratio < 100) && (ratio >= 64)) {   luxdata_int = (((5926 * alsval_ch0)+(1185 * alsval_ch1)))/10000;  }  else {   luxdata_int = 0; #if 1     als_zero_try++;   if(als_zero_try < 2){    APS_DBG("als=0, try to find whether is enable for first time.\n");    mdelay(20);    goto als_data_try;   }else{    APS_DBG("als=0.zifan!!!!!!!\n");   } #endif

 }    APS_DBG("als_value_lux = %d\n", luxdata_int);  return luxdata_int;

  err:  final_lux_val = luxdata_int;  APS_DBG("err als_value_lux = 0x%x\n", luxdata_int);  return luxdata_int; }

 

/*----------------------------------------------------------------------------*/ int ltr559_get_addr(struct alsps_hw *hw, struct ltr559_i2c_addr *addr) {  /***  if(!hw || !addr)  {   return -EFAULT;  }  addr->write_addr= hw->i2c_addr[0];  ***/  return 0; }

/*-----------------------------------------------------------------------------*/ void ltr559_eint_func(void) {  APS_FUN();

 struct ltr559_priv *obj = ltr559_obj;  if(!obj)  {   return;  }    schedule_work(&obj->eint_work);  //schedule_delayed_work(&obj->eint_work); }

 

/*----------------------------------------------------------------------------*/ /*for interrup work mode support -- by liaoxl.lenovo 12.08.2011*/ int ltr559_setup_eint(struct i2c_client *client) {  APS_FUN();  struct ltr559_priv *obj = (struct ltr559_priv *)i2c_get_clientdata(client);       

 ltr559_obj = obj;  mt_set_gpio_dir(GPIO_ALS_EINT_PIN, GPIO_DIR_IN);  mt_set_gpio_mode(GPIO_ALS_EINT_PIN, GPIO_ALS_EINT_PIN_M_EINT);  mt_set_gpio_pull_enable(GPIO_ALS_EINT_PIN, TRUE);  mt_set_gpio_pull_select(GPIO_ALS_EINT_PIN, GPIO_PULL_UP);

 mt_eint_set_hw_debounce(CUST_EINT_ALS_NUM, CUST_EINT_ALS_DEBOUNCE_CN);  mt_eint_registration(CUST_EINT_ALS_NUM, CUST_EINT_ALS_TYPE, ltr559_eint_func, 0);  mt_eint_unmask(CUST_EINT_ALS_NUM);      return 0; }

/*----------------------------------------------------------------------------*/ static void ltr559_power(struct alsps_hw *hw, unsigned int on) {  static unsigned int power_on = 0;

 //APS_LOG("power %s\n", on ? "on" : "off");

 if(hw->power_id != POWER_NONE_MACRO)  {   if(power_on == on)   {    APS_LOG("ignore power control: %d\n", on);   }   else if(on)   {    if(!hwPowerOn(hw->power_id, hw->power_vol, "LTR559"))    {     APS_ERR("power on fails!!\n");    }   }   else   {    if(!hwPowerDown(hw->power_id, "LTR559"))    {     APS_ERR("power off fail!!\n");      }   }  }  power_on = on; }

/*----------------------------------------------------------------------------*/ /*for interrup work mode support -- by liaoxl.lenovo 12.08.2011*/ static int ltr559_check_and_clear_intr(struct i2c_client *client) { //***  APS_FUN();

 int res,intp,intl;  u8 buffer[2];   u8 temp;   //if (mt_get_gpio_in(GPIO_ALS_EINT_PIN) == 1) /*skip if no interrupt*/    //   return 0;     buffer[0] = LTR559_ALS_PS_STATUS;   res = i2c_master_send(client, buffer, 0x1);   if(res <= 0)   {    goto EXIT_ERR;   }   res = i2c_master_recv(client, buffer, 0x1);   if(res <= 0)   {    goto EXIT_ERR;   }   temp = buffer[0];   res = 1;   intp = 0;   intl = 0;   if(0 != (buffer[0] & 0x02))   {    res = 0;    intp = 1;   }   if(0 != (buffer[0] & 0x08))   {    res = 0;    intl = 1;     }     if(0 == res)   {    if((1 == intp) && (0 == intl))    {     buffer[1] = buffer[0] & 0xfD;         }    else if((0 == intp) && (1 == intl))    {     buffer[1] = buffer[0] & 0xf7;    }    else    {     buffer[1] = buffer[0] & 0xf5;    }    buffer[0] = LTR559_ALS_PS_STATUS ;    res = i2c_master_send(client, buffer, 0x2);    if(res <= 0)    {     goto EXIT_ERR;    }    else    {     res = 0;    }   }     return res;    EXIT_ERR:   APS_ERR("ltr559_check_and_clear_intr fail\n");   return 1;

} /*----------------------------------------------------------------------------*/

static int ltr559_check_intr(struct i2c_client *client) {  APS_FUN();

 int res,intp,intl;  u8 buffer[2];

 //if (mt_get_gpio_in(GPIO_ALS_EINT_PIN) == 1) /*skip if no interrupt*/   //    return 0;

 buffer[0] = LTR559_ALS_PS_STATUS;  res = i2c_master_send(client, buffer, 0x1);  if(res <= 0)  {   goto EXIT_ERR;  }  res = i2c_master_recv(client, buffer, 0x1);  if(res <= 0)  {   goto EXIT_ERR;  }  res = 1;  intp = 0;  intl = 0;  if(0 != (buffer[0] & 0x02))  {   res = 0; //Ps int   intp = 1;  }  if(0 != (buffer[0] & 0x08))  {   res = 0;   intl = 1;    }

 return res;

EXIT_ERR:  APS_ERR("ltr559_check_intr fail\n");  return 1; }

static int ltr559_clear_intr(struct i2c_client *client) {  int res;  u8 buffer[2];

 APS_FUN();    buffer[0] = LTR559_ALS_PS_STATUS;  res = i2c_master_send(client, buffer, 0x1);  if(res <= 0)  {   goto EXIT_ERR;  }  res = i2c_master_recv(client, buffer, 0x1);  if(res <= 0)  {   goto EXIT_ERR;  }  APS_DBG("buffer[0] = %d \n",buffer[0]);  buffer[1] = buffer[0] & 0x01;  buffer[0] = LTR559_ALS_PS_STATUS ;

 res = i2c_master_send(client, buffer, 0x2);  if(res <= 0)  {   goto EXIT_ERR;  }  else  {   res = 0;  }

 return res;

EXIT_ERR:  APS_ERR("ltr559_check_and_clear_intr fail\n");  return 1; }

//wisky-lxh@20150108 static int ltr559_init_device(void) {     int error = 0;

 error = ltr559_i2c_write_reg(LTR559_PS_LED, 0x7F);  if(error<0)     {         APS_LOG("ltr559_ps_enable() error3...\n");      return error;  }       error = ltr559_i2c_write_reg(LTR559_PS_N_PULSES, 0x06);  if(error<0)     {         APS_LOG("ltr559_ps_enable() error2\n");      return error;  }

    error = ltr559_i2c_write_reg(LTR559_ALS_MEAS_RATE, 0x08);     if(error<0)     {         APS_LOG("ltr559_ps_enable() error2\n");         return error;     }

    error = ltr559_i2c_write_reg(LTR559_PS_MEAS_RATE, 0x01);     if(error<0)     {         APS_LOG("ltr559_ps_enable() error2\n");         return error;     }  

    error = ltr559_i2c_write_reg(LTR559_PS_THRES_UP_0, ps_trigger_high & 0xff);     if(error<0)     {         APS_LOG("ltr559_ps_enable() error2\n");         return error;     }     error = ltr559_i2c_write_reg(LTR559_PS_THRES_UP_1, (ps_trigger_high>>8) & 0X07);     if(error<0)     {         APS_LOG("ltr559_ps_enable() error2\n");         return error;     }     error = ltr559_i2c_write_reg(LTR559_PS_THRES_LOW_0, 0x0);     if(error<0)     {         APS_LOG("ltr559_ps_enable() error2\n");         return error;     }     error = ltr559_i2c_write_reg(LTR559_PS_THRES_LOW_1, 0x0);     if(error<0)     {         APS_LOG("ltr559_ps_enable() error2\n");         return error;     }

    mdelay(WAKEUP_DELAY);

    return error;

} //end-wisky-lxh

static int ltr559_devinit(void) {  int res;  int init_ps_gain;  int init_als_gain;  u8 databuf[2]; 

 struct i2c_client *client = ltr559_obj->client;

 struct ltr559_priv *obj = ltr559_obj;      mdelay(PON_DELAY);

 //soft reset when device init add by steven  databuf[0] = LTR559_ALS_CONTR;   databuf[1] = 0x02;  res = i2c_master_send(client, databuf, 0x2);  if(res <= 0)  {   goto EXIT_ERR;   return ltr559_ERR_I2C;  }

 /*for interrup work mode support */  if(0 == obj->hw->polling_mode_ps)  {    APS_LOG("eint enable");   ltr559_ps_set_thres();      databuf[0] = LTR559_INTERRUPT;    databuf[1] = 0x01;   res = i2c_master_send(client, databuf, 0x2);   if(res <= 0)   {    goto EXIT_ERR;    return ltr559_ERR_I2C;   }

  databuf[0] = LTR559_INTERRUPT_PERSIST;    databuf[1] = 0x20;   res = i2c_master_send(client, databuf, 0x2);   if(res <= 0)   {    goto EXIT_ERR;    return ltr559_ERR_I2C;   }

 }

 if((res = ltr559_setup_eint(client))!=0)  {   APS_ERR("setup eint: %d\n", res);   return res;  }     //wisky-lxh@20150108  res = ltr559_init_device();  if (res < 0)  {     APS_ERR("ltr559_init_devicet: %d\n", res);   return res;  }  //end-wisky-lxh  if((res = ltr559_check_and_clear_intr(client)))  {   APS_ERR("check/clear intr: %d\n", res);   //    return res;  }

 res = 0;

 EXIT_ERR:  APS_ERR("init dev: %d\n", res);  return res;

} /*----------------------------------------------------------------------------*/

static int ltr559_get_als_value(struct ltr559_priv *obj, u16 als) {  int idx;  int invalid = 0;  APS_DBG("als  = %d\n",als);  for(idx = 0; idx < obj->als_level_num; idx++)  {   if(als < obj->hw->als_level[idx])   {    break;   }  }    if(idx >= obj->als_value_num)  {   APS_ERR("exceed range\n");   idx = obj->als_value_num - 1;  }    if(1 == atomic_read(&obj->als_deb_on))  {   unsigned long endt = atomic_read(&obj->als_deb_end);   if(time_after(jiffies, endt))   {    atomic_set(&obj->als_deb_on, 0);   }      if(1 == atomic_read(&obj->als_deb_on))   {    invalid = 1;   }  }

 if(!invalid)  {   APS_DBG("ALS: %05d => %05d\n", als, obj->hw->als_value[idx]);    return obj->hw->als_value[idx];  }  else  {   APS_ERR("ALS: %05d => %05d (-1)\n", als, obj->hw->als_value[idx]);      return -1;  } } /*----------------------------------------------------------------------------*/ static int ltr559_get_ps_value(struct ltr559_priv *obj, u16 ps) {  int val,  mask = atomic_read(&obj->ps_mask);  int invalid = 0;

 static int val_temp = 5;  if((ps > atomic_read(&obj->ps_thd_val_high)))  {   val = 0;  /*close*/   val_temp = 0;   intr_flag_value = 1;  }    //else if((ps < atomic_read(&obj->ps_thd_val_low))&&(temp_ps[0]  < atomic_read(&obj->ps_thd_val_low)))  else if((ps < atomic_read(&obj->ps_thd_val_low)))  {   val = 5;  /*far away*/   val_temp = 5;   intr_flag_value = 0;  }  else   val = val_temp;         if(atomic_read(&obj->ps_suspend))  {   invalid = 1;  }  else if(1 == atomic_read(&obj->ps_deb_on))  {   unsigned long endt = atomic_read(&obj->ps_deb_end);   if(time_after(jiffies, endt))   {    atomic_set(&obj->ps_deb_on, 0);   }      if (1 == atomic_read(&obj->ps_deb_on))   {    invalid = 1;   }  }  else if (obj->als > 50000)  {   //invalid = 1;   APS_DBG("ligh too high will result to failt proximiy\n");   return 1;  /*far away*/  }

 if(!invalid)  {   APS_DBG("PS:  %05d => %05d\n", ps, val);   return val;  }   else  {   return -1;  }  }

/*----------------------------------------------------------------------------*/

/*----------------------------------------------------------------------------*/ /*for interrup work mode support */ static void ltr559_eint_work(struct work_struct *work) {  struct ltr559_priv *obj = (struct ltr559_priv *)container_of(work, struct ltr559_priv, eint_work);  int err;  hwm_sensor_data sensor_data;  int temp_noise;  // u8 buffer[1]; // u8 reg_value[1];  u8 databuf[2];  int res = 0;  APS_FUN();  err = ltr559_check_intr(obj->client);  if(err < 0)  {   APS_ERR("ltr559_eint_work check intrs: %d\n", err);  }  else  {   //get raw data   obj->ps = ltr559_ps_read();      if(obj->ps < 0)      {       err = -1;       return;      }        APS_DBG("ltr559_eint_work rawdata ps=%d als_ch0=%d!\n",obj->ps,obj->als);   sensor_data.values[0] = ltr559_get_ps_value(obj, obj->ps);   //sensor_data.values[1] = obj->ps;   sensor_data.value_divide = 1;   sensor_data.status = SENSOR_STATUS_ACCURACY_MEDIUM;    /*singal interrupt function add*/   APS_DBG("intr_flag_value=%d\n",intr_flag_value);   if(intr_flag_value){    APS_DBG(" interrupt value ps will < ps_threshold_low");

   databuf[0] = LTR559_PS_THRES_LOW_0;     databuf[1] = (u8)((atomic_read(&obj->ps_thd_val_low)) & 0x00FF);    res = i2c_master_send(obj->client, databuf, 0x2);    if(res <= 0)    {     return;    }    databuf[0] = LTR559_PS_THRES_LOW_1;     databuf[1] = (u8)(((atomic_read(&obj->ps_thd_val_low)) & 0xFF00) >> 8);    res = i2c_master_send(obj->client, databuf, 0x2);    if(res <= 0)    {     return;    }    databuf[0] = LTR559_PS_THRES_UP_0;     databuf[1] = (u8)(0x00FF);    res = i2c_master_send(obj->client, databuf, 0x2);    if(res <= 0)    {     return;    }    databuf[0] = LTR559_PS_THRES_UP_1;    databuf[1] = (u8)((0xFF00) >> 8);;    res = i2c_master_send(obj->client, databuf, 0x2);    //APS_DBG("obj->ps_thd_val_low=%ld !\n",obj->ps_thd_val_low);    if(res <= 0)    {     return;    }   }   else{          //if(obj->ps > 20 && obj->ps < (dynamic_calibrate - 50)){ //wangxiqiang    //if(obj->ps > 20){      if(obj->ps < 100){        atomic_set(&obj->ps_thd_val_high,  obj->ps+80);     atomic_set(&obj->ps_thd_val_low, obj->ps+60);    }else if(obj->ps < 200){     atomic_set(&obj->ps_thd_val_high,  obj->ps+100);     atomic_set(&obj->ps_thd_val_low, obj->ps+80);    }else if(obj->ps < 300){     atomic_set(&obj->ps_thd_val_high,  obj->ps+100);     atomic_set(&obj->ps_thd_val_low, obj->ps+80);    }else if(obj->ps < 400){     atomic_set(&obj->ps_thd_val_high,  obj->ps+100);     atomic_set(&obj->ps_thd_val_low, obj->ps+80);    }else if(obj->ps < 600){     atomic_set(&obj->ps_thd_val_high,  obj->ps+180);     atomic_set(&obj->ps_thd_val_low, obj->ps+90);    }else if(obj->ps < 1000){     atomic_set(&obj->ps_thd_val_high,  obj->ps+300);     atomic_set(&obj->ps_thd_val_low, obj->ps+180);     }else if(obj->ps < 1250){     atomic_set(&obj->ps_thd_val_high,  obj->ps+400);     atomic_set(&obj->ps_thd_val_low, obj->ps+300);    }    else{     atomic_set(&obj->ps_thd_val_high,  1300);     atomic_set(&obj->ps_thd_val_low, 1000);     printk(KERN_ERR "ltr559 the proximity sensor structure is error\n");    }       dynamic_calibrate = obj->ps;

   //} 

   if(obj->ps > 50){     temp_noise = obj->ps - 50;    }else{     temp_noise = 0;    }

   //wake_lock_timeout(&ps_wake_lock,ps_wakeup_timeout*HZ);    databuf[0] = LTR559_PS_THRES_LOW_0;    databuf[1] = (u8)(0 & 0x00FF);//get the noise one time    res = i2c_master_send(obj->client, databuf, 0x2);    if(res <= 0)    {     return;    }    databuf[0] = LTR559_PS_THRES_LOW_1;    databuf[1] = (u8)((0 & 0xFF00) >> 8);    res = i2c_master_send(obj->client, databuf, 0x2);    if(res <= 0)    {     return;    }    databuf[0] = LTR559_PS_THRES_UP_0;     databuf[1] = (u8)((atomic_read(&obj->ps_thd_val_high)) & 0x00FF);    res = i2c_master_send(obj->client, databuf, 0x2);    if(res <= 0)    {     return;    }    databuf[0] = LTR559_PS_THRES_UP_1;    databuf[1] = (u8)(((atomic_read(&obj->ps_thd_val_high)) & 0xFF00) >> 8);;    res = i2c_master_send(obj->client, databuf, 0x2); //   APS_DBG("obj->ps_thd_val_high=%ld !\n",obj->ps_thd_val_high);    if(res <= 0)    {     return;    }   }      sensor_data.value_divide = 1;   sensor_data.status = SENSOR_STATUS_ACCURACY_MEDIUM;   //let up layer to know   if((err = hwmsen_get_interrupt_data(ID_PROXIMITY, &sensor_data)))   {     APS_ERR("call hwmsen_get_interrupt_data fail = %d\n", err);   }  }  ltr559_clear_intr(obj->client);     mt_eint_unmask(CUST_EINT_ALS_NUM);       }

 

/******************************************************************************  * Function Configuration ******************************************************************************/ static int ltr559_open(struct inode *inode, struct file *file) {  file->private_data = ltr559_i2c_client;

 if (!file->private_data)  {   APS_ERR("null pointer!!\n");   return -EINVAL;  }    return nonseekable_open(inode, file); } /*----------------------------------------------------------------------------*/ static int ltr559_release(struct inode *inode, struct file *file) {  file->private_data = NULL;  return 0; } /*----------------------------------------------------------------------------*/

static int ltr559_unlocked_ioctl(struct file *file, unsigned int cmd,        unsigned long arg)       {  struct i2c_client *client = (struct i2c_client*)file->private_data;  struct ltr559_priv *obj = i2c_get_clientdata(client);   int err = 0;  void __user *ptr = (void __user*) arg;  int dat;  uint32_t enable;  APS_DBG("ltr559_unlocked_ioctl cmd= %d\n", cmd);  switch (cmd)  {   case ALSPS_SET_PS_MODE:    if(copy_from_user(&enable, ptr, sizeof(enable)))    {     err = -EFAULT;     goto err_out;    }    if(enable)    {        err = ltr559_ps_enable(ps_gainrange);     if(err < 0)     {      APS_ERR("enable ps fail: %d\n", err);      goto err_out;     }     set_bit(CMC_BIT_PS, &obj->enable);    }    else    {        err = ltr559_ps_disable();     if(err < 0)     {      APS_ERR("disable ps fail: %d\n", err);      goto err_out;     }          clear_bit(CMC_BIT_PS, &obj->enable);    }    break;

  case ALSPS_GET_PS_MODE:    enable = test_bit(CMC_BIT_PS, &obj->enable) ? (1) : (0);    if(copy_to_user(ptr, &enable, sizeof(enable)))    {     err = -EFAULT;     goto err_out;    }    break;

  case ALSPS_GET_PS_DATA:    APS_DBG("ALSPS_GET_PS_DATA\n");       obj->ps = ltr559_ps_read();    if(obj->ps < 0)    {     goto err_out;    }        dat = ltr559_get_ps_value(obj, obj->ps);    if(copy_to_user(ptr, &dat, sizeof(dat)))    {     err = -EFAULT;     goto err_out;    }     break;

  case ALSPS_GET_PS_RAW_DATA:        #if 1    obj->ps = ltr559_ps_read();    if(obj->ps < 0)    {     goto err_out;    }    dat = obj->ps;    #endif

   //dat = prox_val;  //read static variate        if(copy_to_user(ptr, &dat, sizeof(dat)))    {     err = -EFAULT;     goto err_out;    }     break;

  case ALSPS_SET_ALS_MODE:    if(copy_from_user(&enable, ptr, sizeof(enable)))    {     err = -EFAULT;     goto err_out;    }    if(enable)    {        err = ltr559_als_enable(als_gainrange);     if(err < 0)     {      APS_ERR("enable als fail: %d\n", err);      goto err_out;     }     set_bit(CMC_BIT_ALS, &obj->enable);    }    else    {        err = ltr559_als_disable();     if(err < 0)     {      APS_ERR("disable als fail: %d\n", err);      goto err_out;     }     clear_bit(CMC_BIT_ALS, &obj->enable);    }    break;

  case ALSPS_GET_ALS_MODE:    enable = test_bit(CMC_BIT_ALS, &obj->enable) ? (1) : (0);    if(copy_to_user(ptr, &enable, sizeof(enable)))    {     err = -EFAULT;     goto err_out;    }    break;

  case ALSPS_GET_ALS_DATA:       obj->als = ltr559_als_read(als_gainrange);    if(obj->als < 0)    {     goto err_out;    }

   dat = ltr559_get_als_value(obj, obj->als);    if(copy_to_user(ptr, &dat, sizeof(dat)))    {     err = -EFAULT;     goto err_out;    }                 break;

  case ALSPS_GET_ALS_RAW_DATA:       obj->als = ltr559_als_read(als_gainrange);    if(obj->als < 0)    {     goto err_out;    }

   dat = obj->als;    if(copy_to_user(ptr, &dat, sizeof(dat)))    {     err = -EFAULT;     goto err_out;    }                 break;

  default:    APS_ERR("%s not supported = 0x%04x", __FUNCTION__, cmd);    err = -ENOIOCTLCMD;    break;  }

 err_out:  return err;    }

/*----------------------------------------------------------------------------*/ static struct file_operations ltr559_fops = {  //.owner = THIS_MODULE,  .open = ltr559_open,  .release = ltr559_release,  .unlocked_ioctl = ltr559_unlocked_ioctl, }; /*----------------------------------------------------------------------------*/ static struct miscdevice ltr559_device = {  .minor = MISC_DYNAMIC_MINOR,  .name = "als_ps",  .fops = &ltr559_fops, };

static int ltr559_i2c_suspend(struct i2c_client *client, pm_message_t msg) {  struct ltr559_priv *obj = i2c_get_clientdata(client);     int err;  APS_FUN();   

 if(msg.event == PM_EVENT_SUSPEND)  {     if(!obj)   {    APS_ERR("null pointer!!\n");    return -EINVAL;   }      atomic_set(&obj->als_suspend, 1);   err = ltr559_als_disable();   if(err < 0)   {    APS_ERR("disable als: %d\n", err);    return err;   }

  #if 0  //suspend not need ps suspend  not need power down   atomic_set(&obj->ps_suspend, 1);   err = ltr559_ps_disable();   if(err < 0)   {    APS_ERR("disable ps:  %d\n", err);    return err;   }        ltr559_power(obj->hw, 0);

  #endif  }  return 0; } /*----------------------------------------------------------------------------*/ static int ltr559_i2c_resume(struct i2c_client *client) {  struct ltr559_priv *obj = i2c_get_clientdata(client);         int err;  err = 0;  APS_FUN();

 if(!obj)  {   APS_ERR("null pointer!!\n");   return -EINVAL;  }

 ltr559_power(obj->hw, 1); /* err = ltr559_devinit();  if(err < 0)  {   APS_ERR("initialize client fail!!\n");   return err;         }*/  atomic_set(&obj->als_suspend, 0);  if(test_bit(CMC_BIT_ALS, &obj->enable))  {      err = ltr559_als_enable(als_gainrange);      if (err < 0)   {    APS_ERR("enable als fail: %d\n", err);          }  }  //atomic_set(&obj->ps_suspend, 0);  if(test_bit(CMC_BIT_PS,  &obj->enable))  {   //err = ltr559_ps_enable(ps_gainrange);      if (err < 0)   {    APS_ERR("enable ps fail: %d\n", err);                  }  }

 return 0; }

static void ltr559_early_suspend(struct early_suspend *h) {   /*early_suspend is only applied for ALS*/  struct ltr559_priv *obj = container_of(h, struct ltr559_priv, early_drv);    int err;  APS_FUN();   

 if(!obj)  {   APS_ERR("null pointer!!\n");   return;  }    atomic_set(&obj->als_suspend, 1);  err = ltr559_als_disable();  if(err < 0)  {   APS_ERR("disable als fail: %d\n", err);  } }

static void ltr559_late_resume(struct early_suspend *h) {   /*early_suspend is only applied for ALS*/  struct ltr559_priv *obj = container_of(h, struct ltr559_priv, early_drv);          int err;  APS_FUN();

 if(!obj)  {   APS_ERR("null pointer!!\n");   return;  }

 atomic_set(&obj->als_suspend, 0);  if(test_bit(CMC_BIT_ALS, &obj->enable))  {      err = ltr559_als_enable(als_gainrange);   if(err < 0)   {    APS_ERR("enable als fail: %d\n", err);       

  }  } }

int ltr559_ps_operate(void* self, uint32_t command, void* buff_in, int size_in,   void* buff_out, int size_out, int* actualout) {  int err = 0;  int value;  hwm_sensor_data* sensor_data;  struct ltr559_priv *obj = (struct ltr559_priv *)self;    switch (command)  {   case SENSOR_DELAY:    if((buff_in == NULL) || (size_in < sizeof(int)))    {     APS_ERR("Set delay parameter error!\n");     err = -EINVAL;    }    // Do nothing    break;

  case SENSOR_ENABLE:    if((buff_in == NULL) || (size_in < sizeof(int)))    {     APS_ERR("Enable sensor parameter error!\n");     err = -EINVAL;    }    else    {         value = *(int *)buff_in;     if(value)     {         err = ltr559_ps_enable(ps_gainrange);      if(err < 0)      {       APS_ERR("enable ps fail: %d\n", err);       return -1;      }      set_bit(CMC_BIT_PS, &obj->enable);     }     else     {         err = ltr559_ps_disable();      if(err < 0)      {       APS_ERR("disable ps fail: %d\n", err);       return -1;      }      clear_bit(CMC_BIT_PS, &obj->enable);     }    }    break;

  case SENSOR_GET_DATA:    if((buff_out == NULL) || (size_out< sizeof(hwm_sensor_data)))    {     APS_ERR("get sensor data parameter error!\n");     err = -EINVAL;    }    else    {     APS_ERR("get sensor ps data !\n");     sensor_data = (hwm_sensor_data *)buff_out;     obj->ps = ltr559_ps_read();        if(obj->ps < 0)        {         err = -1;         break;        }     sensor_data->values[0] = ltr559_get_ps_value(obj, obj->ps);     //sensor_data->values[1] = obj->ps;  //steven polling mode *#*#3646633#*#*     sensor_data->value_divide = 1;     sensor_data->status = SENSOR_STATUS_ACCURACY_MEDIUM;       }    break;   default:    APS_ERR("proxmy sensor operate function no this parameter %d!\n", command);    err = -1;    break;  }    return err; }

int ltr559_als_operate(void* self, uint32_t command, void* buff_in, int size_in,   void* buff_out, int size_out, int* actualout) {  int err = 0;  int value;  hwm_sensor_data* sensor_data;  struct ltr559_priv *obj = (struct ltr559_priv *)self;

 switch (command)  {   case SENSOR_DELAY:    if((buff_in == NULL) || (size_in < sizeof(int)))    {     APS_ERR("Set delay parameter error!\n");     err = -EINVAL;    }    // Do nothing    break;

  case SENSOR_ENABLE:    if((buff_in == NULL) || (size_in < sizeof(int)))    {     APS_ERR("Enable sensor parameter error!\n");     err = -EINVAL;    }    else    {     value = *(int *)buff_in;         if(value)     {         err = ltr559_als_enable(als_gainrange);      if(err < 0)      {       APS_ERR("enable als fail: %d\n", err);       return -1;      }      set_bit(CMC_BIT_ALS, &obj->enable);     }     else     {         err = ltr559_als_disable();      if(err < 0)      {       APS_ERR("disable als fail: %d\n", err);       return -1;      }      clear_bit(CMC_BIT_ALS, &obj->enable);     }         }    break;

  case SENSOR_GET_DATA:    if((buff_out == NULL) || (size_out< sizeof(hwm_sensor_data)))    {     APS_ERR("get sensor data parameter error!\n");     err = -EINVAL;    }    else    {     APS_ERR("get sensor als data !\n");     sensor_data = (hwm_sensor_data *)buff_out;     obj->als = ltr559_als_read(als_gainrange);                 #if defined(MTK_AAL_SUPPORT)     sensor_data->values[0] = ltr559_get_als_value(obj, obj->als);//wisky-lxh@20150206     #else     sensor_data->values[0] = ltr559_get_als_value(obj, obj->als);     #endif     sensor_data->value_divide = 1;     sensor_data->status = SENSOR_STATUS_ACCURACY_MEDIUM;    }    break;   default:    APS_ERR("light sensor operate function no this parameter %d!\n", command);    err = -1;    break;  }    return err; }

/*----------------------------------------------------------------------------*/ static int ltr559_i2c_detect(struct i2c_client *client, int kind, struct i2c_board_info *info) {     strcpy(info->type, LTR559_DEV_NAME);  return 0; }

/*----------------------------------------------------------------------------*/ static int ltr559_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) {  struct ltr559_priv *obj;  struct hwmsen_object obj_ps, obj_als;  int err = 0;

 if(!(obj = kzalloc(sizeof(*obj), GFP_KERNEL)))  {   err = -ENOMEM;   goto exit;  }  memset(obj, 0, sizeof(*obj));  ltr559_obj = obj;

 obj->hw = get_cust_alsps_hw();  ltr559_get_addr(obj->hw, &obj->addr);

 INIT_WORK(&obj->eint_work, ltr559_eint_work);  obj->client = client;  i2c_set_clientdata(client, obj);   atomic_set(&obj->als_debounce, 300);  atomic_set(&obj->als_deb_on, 0);  atomic_set(&obj->als_deb_end, 0);  atomic_set(&obj->ps_debounce, 300);  atomic_set(&obj->ps_deb_on, 0);  atomic_set(&obj->ps_deb_end, 0);  atomic_set(&obj->ps_mask, 0);  atomic_set(&obj->als_suspend, 0);  atomic_set(&obj->ps_thd_val_high,  obj->hw->ps_threshold_high);  atomic_set(&obj->ps_thd_val_low,  obj->hw->ps_threshold_low);  //atomic_set(&obj->als_cmd_val, 0xDF);  //atomic_set(&obj->ps_cmd_val,  0xC1);  atomic_set(&obj->ps_thd_val,  obj->hw->ps_threshold);  obj->enable = 0;  obj->pending_intr = 0;  obj->als_level_num = sizeof(obj->hw->als_level)/sizeof(obj->hw->als_level[0]);  obj->als_value_num = sizeof(obj->hw->als_value)/sizeof(obj->hw->als_value[0]);    obj->als_modulus = (400*100)/(16*150);//(1/Gain)*(400/Tine), this value is fix after init ATIME and CONTROL register value           //(400)/16*2.72 here is amplify *100  BUG_ON(sizeof(obj->als_level) != sizeof(obj->hw->als_level));  memcpy(obj->als_level, obj->hw->als_level, sizeof(obj->als_level));  BUG_ON(sizeof(obj->als_value) != sizeof(obj->hw->als_value));  memcpy(obj->als_value, obj->hw->als_value, sizeof(obj->als_value));  atomic_set(&obj->i2c_retry, 3);  set_bit(CMC_BIT_ALS, &obj->enable);  set_bit(CMC_BIT_PS, &obj->enable);

 APS_LOG("ltr559_devinit() start...!\n");  ltr559_i2c_client = client;

 if(err = ltr559_devinit())  {   goto exit_init_failed;  }  APS_LOG("ltr559_devinit() ...OK!\n");

 //printk("@@@@@@ manufacturer value:%x\n",ltr559_i2c_read_reg(0x87));

 if(err = misc_register(&ltr559_device))  {   APS_ERR("ltr559_device register failed\n");   goto exit_misc_device_register_failed;  }

   /* Register sysfs attribute */  if(err = ltr559_create_attr(&ltr559_alsps_driver.driver))  {   printk(KERN_ERR "create attribute err = %d\n", err);   goto exit_create_attr_failed;  }

 obj_ps.self = ltr559_obj;  /*for interrup work mode support -- by liaoxl.lenovo 12.08.2011*/  if(1 == obj->hw->polling_mode_ps)  {   obj_ps.polling = 1;  }  else  {   obj_ps.polling = 0;  }  obj_ps.sensor_operate = ltr559_ps_operate;  if(err = hwmsen_attach(ID_PROXIMITY, &obj_ps))  {   APS_ERR("attach fail = %d\n", err);   goto exit_create_attr_failed;  }    obj_als.self = ltr559_obj;  obj_als.polling = 1;  obj_als.sensor_operate = ltr559_als_operate;  if(err = hwmsen_attach(ID_LIGHT, &obj_als))  {   APS_ERR("attach fail = %d\n", err);   goto exit_create_attr_failed;  }

#if defined(CONFIG_HAS_EARLYSUSPEND)  obj->early_drv.level    = EARLY_SUSPEND_LEVEL_DISABLE_FB - 1,  obj->early_drv.suspend  = ltr559_early_suspend,  obj->early_drv.resume   = ltr559_late_resume,     register_early_suspend(&obj->early_drv); #endif

 APS_LOG("%s: OK\n", __func__);  return 0;  exit_create_attr_failed:  misc_deregister(&ltr559_device);  exit_misc_device_register_failed:  exit_init_failed:  //i2c_detach_client(client);  exit_kfree:  kfree(obj);  exit:  ltr559_i2c_client = NULL;           // MT6516_EINTIRQMask(CUST_EINT_ALS_NUM);  /*mask interrupt if fail*/  APS_ERR("%s: err = %d\n", __func__, err);  return err; }

/*----------------------------------------------------------------------------*/

static int ltr559_i2c_remove(struct i2c_client *client) {  int err;   if(err = ltr559_delete_attr(&ltr559_i2c_driver.driver))  {   APS_ERR("ltr559_delete_attr fail: %d\n", err);  }

 if(err = misc_deregister(&ltr559_device))  {   APS_ERR("misc_deregister fail: %d\n", err);     }    ltr559_i2c_client = NULL;  i2c_unregister_device(client);  kfree(i2c_get_clientdata(client));

 return 0; } /*----------------------------------------------------------------------------*/ static int ltr559_probe(struct platform_device *pdev) {  struct alsps_hw *hw = get_cust_alsps_hw();

 ltr559_power(hw, 1);  //ltr559_force[0] = hw->i2c_num;  //ltr559_force[1] = hw->i2c_addr[0];  //APS_DBG("I2C = %d, addr =0x%x\n",ltr559_force[0],ltr559_force[1]);  if(i2c_add_driver(&ltr559_i2c_driver))  {   APS_ERR("add driver error\n");   return -1;  }  return 0; } /*----------------------------------------------------------------------------*/ static int ltr559_remove(struct platform_device *pdev) {  struct alsps_hw *hw = get_cust_alsps_hw();  APS_FUN();     ltr559_power(hw, 0);     i2c_del_driver(&ltr559_i2c_driver);  return 0; } /*----------------------------------------------------------------------------*/

#ifdef CONFIG_OF static const struct of_device_id alsps_of_match[] = {  { .compatible = "mediatek,als_ps", },  {}, }; #endif

static struct platform_driver ltr559_alsps_driver = {  .probe      = ltr559_probe,  .remove     = ltr559_remove,     .driver     =  {   .name = "als_ps",   .owner  = THIS_MODULE,         #ifdef CONFIG_OF   .of_match_table = alsps_of_match,   #endif  } };

#ifdef CONFIG_OF static struct platform_device ltr559_alsps_device={  .name="als_ps",  .id=-1 }; #endif

/*----------------------------------------------------------------------------*/ static int __init ltr559_init(void) {        struct alsps_hw *hw = get_cust_alsps_hw();  APS_FUN();    i2c_register_board_info(hw->i2c_num, &i2c_ltr559, 1);  

 if(platform_driver_register(&ltr559_alsps_driver))  {   APS_ERR("failed to register driver");   return -ENODEV;  }  return 0; } /*----------------------------------------------------------------------------*/ static void __exit ltr559_exit(void) {  APS_FUN();  platform_driver_unregister(&ltr559_alsps_driver); } /*----------------------------------------------------------------------------*/ module_init(ltr559_init); module_exit(ltr559_exit); /*----------------------------------------------------------------------------*/ MODULE_AUTHOR("XX Xx"); MODULE_DESCRIPTION("LTR-559ALS Driver"); MODULE_LICENSE("GPL");

 

gt9xx_driver.c_old:

#include "tpd.h" #include "tpd_custom_gt9xx.h"

#ifndef TPD_NO_GPIO #include "cust_gpio_usage.h" #endif #ifdef TPD_PROXIMITY #include <linux/hwmsensor.h> #include <linux/hwmsen_dev.h> #include <linux/sensors_io.h> #endif

#ifdef CONFIG_OF_TOUCH #include <linux/of.h> #include <linux/of_irq.h> #endif

#if GTP_SUPPORT_I2C_DMA     #include <linux/dma-mapping.h> #endif

#ifdef CONFIG_OF_TOUCH static int irq_flag; static unsigned int touch_irq = 0; #endif

extern char tp_info[20];

extern struct tpd_device *tpd; extern u8 gtp_loading_fw;

int p_gesture_control = 0;

static int tpd_flag = 0; int tpd_halt = 0; static struct task_struct *thread = NULL; static DECLARE_WAIT_QUEUE_HEAD(waiter);

#ifdef TPD_HAVE_BUTTON static int tpd_keys_local[TPD_KEY_COUNT] = TPD_KEYS; static int tpd_keys_dim_local[TPD_KEY_COUNT][4] = TPD_KEYS_DIM; #endif

#if GTP_GESTURE_WAKEUP typedef enum {     DOZE_DISABLED = 0,     DOZE_ENABLED = 1,     DOZE_WAKEUP = 2, }DOZE_T; static DOZE_T doze_status = DOZE_DISABLED; static s8 gtp_enter_doze(struct i2c_client *client); #endif

#if GTP_COVER_CONTROL static RAW_NOTIFIER_HEAD(cover_chain); #endif

#if GTP_P_GESTURE_CONTROL static RAW_NOTIFIER_HEAD(gesture_chain); #endif

struct device *mx_tsp;   //add by chen for MX gesture

#if GTP_CHARGER_SWITCH     #ifdef MT6573         #define CHR_CON0      (0xF7000000+0x2FA00)     #else         extern kal_bool upmu_is_chr_det(void);     #endif     static void gtp_charger_switch(s32 dir_update); #endif

#if GTP_HAVE_TOUCH_KEY const u16 touch_key_array[] = GTP_KEY_TAB; #define GTP_MAX_KEY_NUM ( sizeof( touch_key_array )/sizeof( touch_key_array[0] ) ) #endif

#if (defined(TPD_WARP_START) && defined(TPD_WARP_END)) static int tpd_wb_start_local[TPD_WARP_CNT] = TPD_WARP_START; static int tpd_wb_end_local[TPD_WARP_CNT]   = TPD_WARP_END; #endif

#if (defined(TPD_HAVE_CALIBRATION) && !defined(TPD_CUSTOM_CALIBRATION)) //static int tpd_calmat_local[8]     = TPD_CALIBRATION_MATRIX; static int tpd_def_calmat_local[8] = TPD_CALIBRATION_MATRIX; #endif

#if GTP_SUPPORT_I2C_DMA s32 i2c_dma_write(struct i2c_client *client, u16 addr, u8 *txbuf, s32 len); s32 i2c_dma_read(struct i2c_client *client, u16 addr, u8 *rxbuf, s32 len);

static u8 *gpDMABuf_va = NULL; static dma_addr_t gpDMABuf_pa = 0; #endif

s32 gtp_send_cfg(struct i2c_client *client);

#if GTP_COVER_CONTROL s32 gtp_send_cfg_cover(struct i2c_client *client); #endif

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

#ifdef CONFIG_OF_TOUCH static irqreturn_t tpd_eint_interrupt_handler(unsigned irq, struct irq_desc *desc); #else static void tpd_eint_interrupt_handler(void); #endif

static int touch_event_handler(void *unused); static int tpd_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id); static int tpd_i2c_detect(struct i2c_client *client, struct i2c_board_info *info); static int tpd_i2c_remove(struct i2c_client *client); s32 gtp_i2c_read_dbl_check(struct i2c_client *client, u16 addr, u8 *rxbuf, int len);

#ifndef MT6572 extern void mt65xx_eint_set_hw_debounce(kal_uint8 eintno, kal_uint32 ms); extern kal_uint32 mt65xx_eint_set_sens(kal_uint8 eintno, kal_bool sens); extern void mt65xx_eint_registration(kal_uint8 eintno, kal_bool Dbounce_En,                                      kal_bool ACT_Polarity, void (EINT_FUNC_PTR)(void),                                      kal_bool auto_umask); #endif

#if GTP_CREATE_WR_NODE extern s32 init_wr_node(struct i2c_client *); extern void uninit_wr_node(void); #endif

#if (GTP_ESD_PROTECT || GTP_COMPATIBLE_MODE) static void force_reset_guitar(void); #endif

#if GTP_ESD_PROTECT static int clk_tick_cnt = 200; static struct delayed_work gtp_esd_check_work; static struct workqueue_struct *gtp_esd_check_workqueue = NULL; static s32 gtp_init_ext_watchdog(struct i2c_client *client); static void gtp_esd_check_func(struct work_struct *); void gtp_esd_switch(struct i2c_client *client, s32 on); u8 esd_running = 0; spinlock_t esd_lock; #endif

#ifdef TPD_PROXIMITY #define TPD_PROXIMITY_VALID_REG                   0x814E #define TPD_PROXIMITY_ENABLE_REG                  0x8042 static u8 tpd_proximity_flag = 0; static u8 tpd_proximity_detect = 1;//0-->close ; 1--> far away #endif

struct i2c_client *i2c_client_point = NULL; static const struct i2c_device_id tpd_i2c_id[] = {{"gt9xx", 0}, {}}; static unsigned short force[] = {0, 0xBA, I2C_CLIENT_END, I2C_CLIENT_END}; static const unsigned short *const forces[] = { force, NULL }; //static struct i2c_client_address_data addr_data = { .forces = forces,}; static struct i2c_board_info __initdata i2c_tpd = { I2C_BOARD_INFO("gt9xx", (0xBA >> 1))}; static struct i2c_driver tpd_i2c_driver = {     .probe = tpd_i2c_probe,     .remove = tpd_i2c_remove,     .detect = tpd_i2c_detect,     .driver.name = "gt9xx",     .id_table = tpd_i2c_id,     .address_list = (const unsigned short *) forces, };

static u8 config[GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH]     = {GTP_REG_CONFIG_DATA >> 8, GTP_REG_CONFIG_DATA & 0xff}; #if GTP_CHARGER_SWITCH static u8 gtp_charger_config[GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH]  = {GTP_REG_CONFIG_DATA >> 8, GTP_REG_CONFIG_DATA & 0xff}; #endif

#pragma pack(1) typedef struct {     u16 pid;                 //product id   //     u16 vid;                 //version id   // } st_tpd_info; #pragma pack()

st_tpd_info tpd_info; u8 int_type = 0; u32 abs_x_max = 0; u32 abs_y_max = 0; u8 gtp_rawdiff_mode = 0; u8 cfg_len = 0; u8 pnl_init_error = 0;

#if GTP_COVER_CONTROL static u8 config_cover[GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH]     = {GTP_REG_CONFIG_DATA >> 8, GTP_REG_CONFIG_DATA & 0xff}; #if GTP_CHARGER_SWITCH static u8 gtp_charger_config_cover[GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH]  = {GTP_REG_CONFIG_DATA >> 8, GTP_REG_CONFIG_DATA & 0xff}; #endif u8 cfg_cover_len = 0; u8 pnl_cover_init_error = 0; #endif

#if GTP_WITH_PEN struct input_dev *pen_dev; #endif

#if GTP_COMPATIBLE_MODE u8 driver_num = 0; u8 sensor_num = 0;

#if GTP_COVER_CONTROL u8 driver_num_cover = 0; u8 sensor_num_cover = 0; #endif

u8 gtp_ref_retries = 0; u8 gtp_clk_retries = 0; CHIP_TYPE_T gtp_chip_type = CHIP_TYPE_GT9; u8 rqst_processing = 0; u8 is_950 = 0;

extern u8 gup_check_fs_mounted(char *path_name); extern u8 gup_clk_calibration(void); extern s32 gup_fw_download_proc(void *dir, u8 dwn_mode); void gtp_get_chip_type(struct i2c_client *client); u8 gtp_fw_startup(struct i2c_client *client); static u8 gtp_bak_ref_proc(struct i2c_client *client, u8 mode); static u8 gtp_main_clk_proc(struct i2c_client *client); static void gtp_recovery_reset(struct i2c_client *client); #endif

/* proc file system */ s32 i2c_read_bytes(struct i2c_client *client, u16 addr, u8 *rxbuf, int len); s32 i2c_write_bytes(struct i2c_client *client, u16 addr, u8 *txbuf, int len);

static ssize_t gt91xx_config_read_proc(struct file *, char __user *, size_t, loff_t *); static ssize_t gt91xx_config_write_proc(struct file *, const char __user *, size_t, loff_t *);

static struct proc_dir_entry *gt91xx_config_proc = NULL; static const struct file_operations config_proc_ops = {     .owner = THIS_MODULE,     .read = gt91xx_config_read_proc,     .write = gt91xx_config_write_proc, };

#define VELOCITY_CUSTOM #ifdef VELOCITY_CUSTOM #include <linux/device.h> #include <linux/miscdevice.h> #include <asm/uaccess.h>

#ifndef TPD_VELOCITY_CUSTOM_X #define TPD_VELOCITY_CUSTOM_X 10 #endif #ifndef TPD_VELOCITY_CUSTOM_Y #define TPD_VELOCITY_CUSTOM_Y 10 #endif

// for magnify velocity******************************************** #define TOUCH_IOC_MAGIC 'A'

#define TPD_GET_VELOCITY_CUSTOM_X _IO(TOUCH_IOC_MAGIC,0) #define TPD_GET_VELOCITY_CUSTOM_Y _IO(TOUCH_IOC_MAGIC,1)

int g_v_magnify_x = TPD_VELOCITY_CUSTOM_X; int g_v_magnify_y = TPD_VELOCITY_CUSTOM_Y;

#if GTP_COVER_CONTROL int register_cover_notifier(struct notifier_block *nb) {   return raw_notifier_chain_register(&cover_chain, nb); }

int unregister_cover_notifier(struct notifier_block *nb) {   return raw_notifier_chain_unregister(&cover_chain,nb); }

int cover_notifier_call_chain(unsigned long val, void *v) {   return raw_notifier_call_chain(&cover_chain, val, v); } EXPORT_SYMBOL(cover_notifier_call_chain);

static int cover_event(struct notifier_block *this, unsigned long event, void *ptr) {   GTP_DEBUG("cover_event event=%ld\n",event);   if(event==0)   {    gtp_send_cfg(i2c_client_point);   }   else   {    gtp_send_cfg_cover(i2c_client_point);   }   return 0; }

static struct notifier_block cover_notifier1 = {    .notifier_call = cover_event, }; #endif

#if GTP_P_GESTURE_CONTROL int register_gesture_notifier(struct notifier_block *nb) {   return raw_notifier_chain_register(&gesture_chain, nb); }

int unregister_gesture_notifier(struct notifier_block *nb) {   return raw_notifier_chain_unregister(&gesture_chain,nb); }

int gesture_notifier_call_chain(unsigned long val, void *v) {   return raw_notifier_call_chain(&gesture_chain, val, v); } EXPORT_SYMBOL(gesture_notifier_call_chain);

static int gesture_event(struct notifier_block *this, unsigned long event, void *ptr) {   GTP_DEBUG("gesture_event event=%ld\n",event);   if(event==0)   {    p_gesture_control = 0;   }   else   {    p_gesture_control = 1;   }   return 0; }

static struct notifier_block gesture_notifier1 = {    .notifier_call = gesture_event, }; #endif

 

//add by chen for MX gesture u8 gesture_three_byte_one = 0; u8 gesture_three_byte_two = 0; u8 gesture_three_byte_three = 0; u8 gesture_three_byte_four = 0; int gesture_data=0; static ssize_t gesture_data_store(struct device* dev, struct device_attribute *attr,                                   const char *buf, size_t count) {  /*  struct alsps_context *cxt = NULL;  //int err =0;  ALSPS_LOG("als_store_active buf=%s\n",buf);  mutex_lock(&alsps_context_obj->alsps_op_mutex);  cxt = alsps_context_obj;

    if (!strncmp(buf, "1", 1))  {        als_enable_data(1);      }  else if (!strncmp(buf, "0", 1))  {        als_enable_data(0);      }  else  {    ALSPS_ERR(" alsps_store_active error !!\n");  }  mutex_unlock(&alsps_context_obj->alsps_op_mutex);  ALSPS_LOG(" alsps_store_active done\n");     return count;  */     return 0; } /*----------------------------------------------------------------------------*/ static ssize_t gesture_data_show(struct device* dev,                                  struct device_attribute *attr, char *buf) { /*  struct alsps_context *cxt = NULL;  int div = 0;  cxt = alsps_context_obj;  div=cxt->als_data.vender_div;  ALSPS_LOG("als vender_div value: %d\n", div);  return snprintf(buf, PAGE_SIZE, "%d\n", div); */  GTP_DEBUG("gesture_data_show gesture_data=%x\n",gesture_data);  return snprintf(buf, PAGE_SIZE, "%d\n", gesture_data); }

static ssize_t gesture_control_node_store(struct device* dev, struct device_attribute *attr,                                   const char *buf, size_t count) {      u32 value,value1,value2;     sscanf(buf, "%x", &value);     value1 = value&0x000000ff;     value2 = (value>>16)&0x000000ff;     if(value2 == 1)     {      gesture_three_byte_one = value1;     }     else if(value2 == 2)     {      gesture_three_byte_two = value1;     }     else if(value2 == 3)     {      gesture_three_byte_three = value1;     }     else if(value2 == 4)     {      gesture_three_byte_four = value1;     }     GTP_DEBUG("gesture_three_byte_one=%x,gesture_three_byte_two=%x,gesture_three_byte_three=%x,gesture_three_byte_four=%x\n",gesture_three_byte_one,gesture_three_byte_two,gesture_three_byte_three,gesture_three_byte_four);     return count; } /*----------------------------------------------------------------------------*/ static ssize_t gesture_control_node_show(struct device* dev,                                  struct device_attribute *attr, char *buf) {  return 0; }

static ssize_t gesture_control_store(struct device* dev, struct device_attribute *attr,                                   const char *buf, size_t count) {      if(buf[2] == 1)     {      gesture_three_byte_one = buf[0];     }     else if(buf[2] == 2)     {      gesture_three_byte_two = buf[0];     }     else if(buf[2] == 3)     {      gesture_three_byte_three = buf[0];     }     else if(buf[2] == 4)     {      gesture_three_byte_four = buf[0];     }     GTP_DEBUG("gesture_three_byte_one=%x,gesture_three_byte_two=%x,gesture_three_byte_three=%x,gesture_three_byte_four=%x\n",gesture_three_byte_one,gesture_three_byte_two,gesture_three_byte_three,gesture_three_byte_four);     return count; } /*----------------------------------------------------------------------------*/ static ssize_t gesture_control_show(struct device* dev,                                  struct device_attribute *attr, char *buf) {  return 0; }

 

static ssize_t cover_control_store(struct device* dev, struct device_attribute *attr,                                   const char *buf, size_t count) {   u32 value = 0;  u8 buf_value = buf[0];      sscanf(buf, "%d", &value);  GTP_DEBUG("cover_control_store buf_value=%d,value=%d\n",buf_value,value);  if(value==0)        {        gtp_send_cfg(i2c_client_point);        }       else       {       gtp_send_cfg_cover(i2c_client_point);       }      return 0; } /*----------------------------------------------------------------------------*/ static ssize_t cover_control_show(struct device* dev,                                  struct device_attribute *attr, char *buf) {  return 0; }

DEVICE_ATTR(gesture_data,       S_IWUSR | S_IRUGO, gesture_data_show, gesture_data_store); DEVICE_ATTR(gesture_control_node,        S_IWUSR | S_IRUGO, gesture_control_node_show,  gesture_control_node_store); DEVICE_ATTR(cover_control,        S_IWUSR | S_IRUGO, cover_control_show,  cover_control_store); DEVICE_ATTR(gesture_control,        S_IWUSR | S_IRUGO, gesture_control_show,  gesture_control_store);

static struct attribute *gesture_attributes[] = {  &dev_attr_gesture_data.attr,  &dev_attr_gesture_control_node.attr,  &dev_attr_gesture_control.attr,  &dev_attr_cover_control.attr,  NULL };

static struct attribute_group gesture_attribute_group = {  .attrs = gesture_attributes }; //add end

static int tpd_misc_open(struct inode *inode, struct file *file) {     return nonseekable_open(inode, file); }

static int tpd_misc_release(struct inode *inode, struct file *file) {     return 0; }

static long tpd_unlocked_ioctl(struct file *file, unsigned int cmd,                                unsigned long arg) {     //char strbuf[256];     void __user *data;

    long err = 0;

    if (_IOC_DIR(cmd) & _IOC_READ)     {         err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd));     }     else if (_IOC_DIR(cmd) & _IOC_WRITE)     {         err = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd));     }

    if (err)     {         printk("tpd: access error: %08X, (%2d, %2d)\n", cmd, _IOC_DIR(cmd), _IOC_SIZE(cmd));         return -EFAULT;     }

    switch (cmd)     {         case TPD_GET_VELOCITY_CUSTOM_X:             data = (void __user *) arg;

            if (data == NULL)             {                 err = -EINVAL;                 break;             }

            if (copy_to_user(data, &g_v_magnify_x, sizeof(g_v_magnify_x)))             {                 err = -EFAULT;                 break;             }

            break;

        case TPD_GET_VELOCITY_CUSTOM_Y:             data = (void __user *) arg;

            if (data == NULL)             {                 err = -EINVAL;                 break;             }

            if (copy_to_user(data, &g_v_magnify_y, sizeof(g_v_magnify_y)))             {                 err = -EFAULT;                 break;             }

            break;

        default:             printk("tpd: unknown IOCTL: 0x%08x\n", cmd);             err = -ENOIOCTLCMD;             break;

    }

    return err; }

static struct file_operations tpd_fops = { //  .owner = THIS_MODULE,     .open = tpd_misc_open,     .release = tpd_misc_release,     .unlocked_ioctl = tpd_unlocked_ioctl, }; /*----------------------------------------------------------------------------*/ static struct miscdevice tpd_misc_device = {     .minor = MISC_DYNAMIC_MINOR,     .name = "touch",     .fops = &tpd_fops, };

//********************************************** #endif

static int tpd_i2c_detect(struct i2c_client *client, struct i2c_board_info *info) {     strcpy(info->type, "mtk-tpd");     return 0; }

#ifdef TPD_PROXIMITY static s32 tpd_get_ps_value(void) {     return tpd_proximity_detect; }

static s32 tpd_enable_ps(s32 enable) {     u8  state;     s32 ret = -1;

    if (enable)     {         state = 1;         tpd_proximity_flag = 1;         GTP_INFO("TPD proximity function to be on.");     }     else     {         state = 0;         tpd_proximity_flag = 0;         GTP_INFO("TPD proximity function to be off.");     }

    ret = i2c_write_bytes(i2c_client_point, TPD_PROXIMITY_ENABLE_REG, &state, 1);

    if (ret < 0)     {         GTP_ERROR("TPD %s proximity cmd failed.", state ? "enable" : "disable");         return ret;     }

    GTP_INFO("TPD proximity function %s success.", state ? "enable" : "disable");     return 0; }

s32 tpd_ps_operate(void *self, u32 command, void *buff_in, s32 size_in,                    void *buff_out, s32 size_out, s32 *actualout) {     s32 err = 0;     s32 value;     hwm_sensor_data *sensor_data;

    switch (command)     {         case SENSOR_DELAY:             if ((buff_in == NULL) || (size_in < sizeof(int)))             {                 GTP_ERROR("Set delay parameter error!");                 err = -EINVAL;             }

            // Do nothing             break;

        case SENSOR_ENABLE:             if ((buff_in == NULL) || (size_in < sizeof(int)))             {                 GTP_ERROR("Enable sensor parameter error!");                 err = -EINVAL;             }             else             {                 value = *(int *)buff_in;                 err = tpd_enable_ps(value);             }

            break;

        case SENSOR_GET_DATA:             if ((buff_out == NULL) || (size_out < sizeof(hwm_sensor_data)))             {                 GTP_ERROR("Get sensor data parameter error!");                 err = -EINVAL;             }             else             {                 sensor_data = (hwm_sensor_data *)buff_out;                 sensor_data->values[0] = tpd_get_ps_value();                 sensor_data->value_divide = 1;                 sensor_data->status = SENSOR_STATUS_ACCURACY_MEDIUM;             }

            break;

        default:             GTP_ERROR("proxmy sensor operate function no this parameter %d!\n", command);             err = -1;             break;     }

    return err; } #endif

static ssize_t gt91xx_config_read_proc(struct file *file, char __user *page, size_t size, loff_t *ppos) {     char *ptr = page;     char temp_data[GTP_CONFIG_MAX_LENGTH + 2] = {0};     int i;         if (*ppos)  // CMD call again     {         return 0;     }         ptr += sprintf(ptr, "==== GT9XX config init value====\n");

    for (i = 0 ; i < GTP_CONFIG_MAX_LENGTH ; i++)     {         ptr += sprintf(ptr, "0x%02X ", config[i + 2]);

        if (i % 8 == 7)             ptr += sprintf(ptr, "\n");     }

    ptr += sprintf(ptr, "\n");

    ptr += sprintf(ptr, "==== GT9XX config real value====\n");     i2c_read_bytes(i2c_client_point, GTP_REG_CONFIG_DATA, temp_data, GTP_CONFIG_MAX_LENGTH);

    for (i = 0 ; i < GTP_CONFIG_MAX_LENGTH ; i++)     {         ptr += sprintf(ptr, "0x%02X ", temp_data[i]);

        if (i % 8 == 7)             ptr += sprintf(ptr, "\n");     }     *ppos += ptr - page;     return (ptr - page); }

static ssize_t gt91xx_config_write_proc(struct file *filp, const char __user *buffer, size_t count, loff_t *off) {     s32 ret = 0;

    GTP_DEBUG("write count %zd\n", count);

    if (count > GTP_CONFIG_MAX_LENGTH)     {         GTP_ERROR("size not match [%d:%zd]\n", GTP_CONFIG_MAX_LENGTH, count);         return -EFAULT;     }

    if (copy_from_user(&config[2], buffer, count))     {         GTP_ERROR("copy from user fail\n");         return -EFAULT;     }

    ret = gtp_send_cfg(i2c_client_point);     abs_x_max = (config[RESOLUTION_LOC + 1] << 8) + config[RESOLUTION_LOC];     abs_y_max = (config[RESOLUTION_LOC + 3] << 8) + config[RESOLUTION_LOC + 2];     int_type = (config[TRIGGER_LOC]) & 0x03;

    if (ret < 0)     {         GTP_ERROR("send config failed.");     }

    return count; }

#if GTP_SUPPORT_I2C_DMA s32 i2c_dma_read(struct i2c_client *client, u16 addr, u8 *rxbuf, s32 len) {     int ret;     s32 retry = 0;     u8 buffer[2];

    struct i2c_msg msg[2] =     {         {             .addr = (client->addr & I2C_MASK_FLAG),             .flags = 0,             .buf = buffer,             .len = 2,             .timing = I2C_MASTER_CLOCK         },         {             .addr = (client->addr & I2C_MASK_FLAG),             .ext_flag = (client->ext_flag | I2C_ENEXT_FLAG | I2C_DMA_FLAG),             .flags = I2C_M_RD,             .buf = (u8*)gpDMABuf_pa,                 .len = len,             .timing = I2C_MASTER_CLOCK         },     };         buffer[0] = (addr >> 8) & 0xFF;     buffer[1] = addr & 0xFF;

    if (rxbuf == NULL)         return -1;

    //GTP_DEBUG("dma i2c read: 0x%04X, %d bytes(s)", addr, len);     for (retry = 0; retry < 5; ++retry)     {         ret = i2c_transfer(client->adapter, &msg[0], 2);         if (ret < 0)         {             continue;         }         memcpy(rxbuf, gpDMABuf_va, len);         return 0;     }     GTP_ERROR("Dma I2C Read Error: 0x%04X, %d byte(s), err-code: %d", addr, len, ret);     return ret; }

s32 i2c_dma_write(struct i2c_client *client, u16 addr, u8 *txbuf, s32 len) {     int ret;     s32 retry = 0;     u8 *wr_buf = gpDMABuf_va;         struct i2c_msg msg =     {         .addr = (client->addr & I2C_MASK_FLAG),         .ext_flag = (client->ext_flag | I2C_ENEXT_FLAG | I2C_DMA_FLAG),         .flags = 0,         .buf = (u8*)gpDMABuf_pa,         .len = 2 + len,         .timing = I2C_MASTER_CLOCK     };         wr_buf[0] = (u8)((addr >> 8) & 0xFF);     wr_buf[1] = (u8)(addr & 0xFF);

    if (txbuf == NULL)         return -1;         //GTP_DEBUG("dma i2c write: 0x%04X, %d bytes(s)", addr, len);     memcpy(wr_buf+2, txbuf, len);     for (retry = 0; retry < 5; ++retry)     {         ret = i2c_transfer(client->adapter, &msg, 1);         if (ret < 0)         {             continue;         }         return 0;     }     GTP_ERROR("Dma I2C Write Error: 0x%04X, %d byte(s), err-code: %d", addr, len, ret);     return ret; }

s32 i2c_read_bytes_dma(struct i2c_client *client, u16 addr, u8 *rxbuf, s32 len) {     s32 left = len;     s32 read_len = 0;     u8 *rd_buf = rxbuf;     s32 ret = 0;            //GTP_DEBUG("Read bytes dma: 0x%04X, %d byte(s)", addr, len);     while (left > 0)     {         if (left > GTP_DMA_MAX_TRANSACTION_LENGTH)         {             read_len = GTP_DMA_MAX_TRANSACTION_LENGTH;         }         else         {             read_len = left;         }         ret = i2c_dma_read(client, addr, rd_buf, read_len);         if (ret < 0)         {             GTP_ERROR("dma read failed");             return -1;         }                 left -= read_len;         addr += read_len;         rd_buf += read_len;     }     return 0; }

s32 i2c_write_bytes_dma(struct i2c_client *client, u16 addr, u8 *txbuf, s32 len) {

    s32 ret = 0;     s32 write_len = 0;     s32 left = len;     u8 *wr_buf = txbuf;         //GTP_DEBUG("Write bytes dma: 0x%04X, %d byte(s)", addr, len);     while (left > 0)     {         if (left > GTP_DMA_MAX_I2C_TRANSFER_SIZE)         {             write_len = GTP_DMA_MAX_I2C_TRANSFER_SIZE;         }         else         {             write_len = left;         }         ret = i2c_dma_write(client, addr, wr_buf, write_len);                 if (ret < 0)         {             GTP_ERROR("dma i2c write failed!");             return -1;         }                 left -= write_len;         addr += write_len;         wr_buf += write_len;     }     return 0; } #endif

int i2c_read_bytes_non_dma(struct i2c_client *client, u16 addr, u8 *rxbuf, int len) {     u8 buffer[GTP_ADDR_LENGTH];     u8 retry;     u16 left = len;     u16 offset = 0;

    struct i2c_msg msg[2] =     {         {             .addr = ((client->addr &I2C_MASK_FLAG) | (I2C_ENEXT_FLAG)),             //.addr = ((client->addr &I2C_MASK_FLAG) | (I2C_PUSHPULL_FLAG)),             .flags = 0,             .buf = buffer,             .len = GTP_ADDR_LENGTH,             .timing = I2C_MASTER_CLOCK         },         {             .addr = ((client->addr &I2C_MASK_FLAG) | (I2C_ENEXT_FLAG)),             //.addr = ((client->addr &I2C_MASK_FLAG) | (I2C_PUSHPULL_FLAG)),             .flags = I2C_M_RD,             .timing = I2C_MASTER_CLOCK         },     };

    if (rxbuf == NULL)         return -1;

    //GTP_DEBUG("i2c_read_bytes to device %02X address %04X len %d\n", client->addr, addr, len);

    while (left > 0)     {         buffer[0] = ((addr + offset) >> 8) & 0xFF;         buffer[1] = (addr + offset) & 0xFF;

        msg[1].buf = &rxbuf[offset];

        if (left > MAX_TRANSACTION_LENGTH)         {             msg[1].len = MAX_TRANSACTION_LENGTH;             left -= MAX_TRANSACTION_LENGTH;             offset += MAX_TRANSACTION_LENGTH;         }         else         {             msg[1].len = left;             left = 0;         }

        retry = 0;

        while (i2c_transfer(client->adapter, &msg[0], 2) != 2)         {             retry++;

            //if (retry == 20)             if (retry == 5)             {                 GTP_ERROR("I2C read 0x%X length=%d failed\n", addr + offset, len);                 return -1;             }         }     }

    return 0; }

int i2c_read_bytes(struct i2c_client *client, u16 addr, u8 *rxbuf, int len) { #if GTP_SUPPORT_I2C_DMA     return i2c_read_bytes_dma(client, addr, rxbuf, len); #else     return i2c_read_bytes_non_dma(client, addr, rxbuf, len); #endif }

s32 gtp_i2c_read(struct i2c_client *client, u8 *buf, s32 len) {     s32 ret = -1;     u16 addr = (buf[0] << 8) + buf[1];

    ret = i2c_read_bytes_non_dma(client, addr, &buf[2], len - 2);

    if (!ret)     {         return 2;     }     else     {     #if GTP_GESTURE_WAKEUP         if (DOZE_ENABLED == doze_status)         {             return ret;         }     #endif     #if GTP_COMPATIBLE_MODE         if (CHIP_TYPE_GT9F == gtp_chip_type)         {             gtp_recovery_reset(client);         }         else     #endif         {             gtp_reset_guitar(client, 20);         }         return ret;     } }

s32 gtp_i2c_read_dbl_check(struct i2c_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; }

int i2c_write_bytes_non_dma(struct i2c_client *client, u16 addr, u8 *txbuf, int len) {     u8 buffer[MAX_TRANSACTION_LENGTH];     u16 left = len;     u16 offset = 0;     u8 retry = 0;

    struct i2c_msg msg =     {         .addr = ((client->addr &I2C_MASK_FLAG) | (I2C_ENEXT_FLAG)),         //.addr = ((client->addr &I2C_MASK_FLAG) | (I2C_PUSHPULL_FLAG)),         .flags = 0,         .buf = buffer,         .timing = I2C_MASTER_CLOCK,     };

    if (txbuf == NULL)         return -1;

    //GTP_DEBUG("i2c_write_bytes to device %02X address %04X len %d\n", client->addr, addr, len);

    while (left > 0)     {         retry = 0;

        buffer[0] = ((addr + offset) >> 8) & 0xFF;         buffer[1] = (addr + offset) & 0xFF;

        if (left > MAX_I2C_TRANSFER_SIZE)         {             memcpy(&buffer[GTP_ADDR_LENGTH], &txbuf[offset], MAX_I2C_TRANSFER_SIZE);             msg.len = MAX_TRANSACTION_LENGTH;             left -= MAX_I2C_TRANSFER_SIZE;             offset += MAX_I2C_TRANSFER_SIZE;         }         else         {             memcpy(&buffer[GTP_ADDR_LENGTH], &txbuf[offset], left);             msg.len = left + GTP_ADDR_LENGTH;             left = 0;         }

        //GTP_DEBUG("byte left %d offset %d\n", left, offset);

        while (i2c_transfer(client->adapter, &msg, 1) != 1)         {             retry++;

            //if (retry == 20)             if (retry == 5)             {                 GTP_ERROR("I2C write 0x%X%X length=%d failed\n", buffer[0], buffer[1], len);                 return -1;             }         }     }

    return 0; }

int i2c_write_bytes(struct i2c_client *client, u16 addr, u8 *txbuf, int len) { #if GTP_SUPPORT_I2C_DMA     return i2c_write_bytes_dma(client, addr, txbuf, len); #else     return i2c_write_bytes_non_dma(client, addr, txbuf, len); #endif }

s32 gtp_i2c_write(struct i2c_client *client, u8 *buf, s32 len) {     s32 ret = -1;     u16 addr = (buf[0] << 8) + buf[1];

    ret = i2c_write_bytes_non_dma(client, addr, &buf[2], len - 2);

    if (!ret)     {         return 1;     }     else     {     #if GTP_GESTURE_WAKEUP         if (DOZE_ENABLED == doze_status)         {             return ret;         }     #endif     #if GTP_COMPATIBLE_MODE         if (CHIP_TYPE_GT9F == gtp_chip_type)         {             gtp_recovery_reset(client);         }         else     #endif         {             gtp_reset_guitar(client, 20);         }         return ret;     } }

 

/******************************************************* Function:     Send config Function.

Input:     client: i2c client.

Output:     Executive outcomes.0--success,non-0--fail. *******************************************************/ s32 gtp_send_cfg(struct i2c_client *client) {     s32 ret = 1;

#if GTP_DRIVER_SEND_CFG     s32 retry = 0;

 if (pnl_init_error)     {         GTP_INFO("Error occurred in init_panel, no config sent!");         return 0;     }         GTP_INFO("Driver Send Config");     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; } #if GTP_CHARGER_SWITCH static int gtp_send_chr_cfg(struct i2c_client *client) {  s32 ret = 1; #if GTP_DRIVER_SEND_CFG     s32 retry = 0;

 if (pnl_init_error) {         GTP_INFO("Error occurred in init_panel, no config sent!");         return 0;     }         GTP_INFO("Driver Send Config");     for (retry = 0; retry < 5; retry++) {         ret = gtp_i2c_write(client, gtp_charger_config, GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH);         if (ret > 0) {             break;         }     } #endif   return ret; } #endif

/******************************************************* Function:     Send config Function.

Input:     client: i2c client.

Output:     Executive outcomes.0--success,non-0--fail. *******************************************************/ #if GTP_COVER_CONTROL s32 gtp_send_cfg_cover(struct i2c_client *client) {     s32 ret = 1;

#if GTP_DRIVER_SEND_CFG     s32 retry = 0;

 if (pnl_cover_init_error)     {         GTP_INFO("Error occurred in init_panel, no config sent!");         return 0;     }         GTP_INFO("Driver Send Config");     for (retry = 0; retry < 5; retry++)     {         ret = gtp_i2c_write(client, config_cover, GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH);

        if (ret > 0)         {             break;         }     } #endif     return ret; } #endif /******************************************************* Function:     Read goodix touchscreen version function.

Input:     client: i2c client struct.     version:address to store version info

Output:     Executive outcomes.0---succeed. *******************************************************/ s32 gtp_read_version(struct i2c_client *client, u16 *version) {     s32 ret = -1;     s32 i;     u8 buf[8] = {GTP_REG_VERSION >> 8, GTP_REG_VERSION & 0xff};

    GTP_DEBUG_FUNC();

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

    if (ret < 0)     {         GTP_ERROR("GTP read version failed");         return ret;     }

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

    tpd_info.vid = *version;     tpd_info.pid = 0x00;

    for (i = 0; i < 4; i++)     {         if (buf[i + 2] < 0x30)break;

        tpd_info.pid |= ((buf[i + 2] - 0x30) << ((3 - i) * 4));     }

    if (buf[5] == 0x00)     {                GTP_INFO("IC VERSION: %c%c%c_%02x%02x",              buf[2], buf[3], buf[4], buf[7], buf[6]);      }     else     {         GTP_INFO("IC VERSION:%c%c%c%c_%02x%02x",              buf[2], buf[3], buf[4], buf[5], buf[7], buf[6]);     }     return ret; }

/******************************************************* Function:     GTP initialize function.

Input:     client: i2c client private struct.

Output:     Executive outcomes.0---succeed. *******************************************************/ static s32 gtp_init_panel(struct i2c_client *client) {     s32 ret = 0;     char *info = tp_info;

#if GTP_DRIVER_SEND_CFG     s32 i;     u8 check_sum = 0;     u8 opr_buf[16];     u8 sensor_id = 0;   u8 drv_cfg_version;   u8 flash_cfg_version;

    u8 cfg_info_group0[] = CTP_CFG_GROUP0;     u8 cfg_info_group1[] = CTP_CFG_GROUP1;     u8 cfg_info_group2[] = CTP_CFG_GROUP2;     u8 cfg_info_group3[] = CTP_CFG_GROUP3;     u8 cfg_info_group4[] = CTP_CFG_GROUP4;     u8 cfg_info_group5[] = CTP_CFG_GROUP5;     u8 *send_cfg_buf[] = {cfg_info_group0, cfg_info_group1, cfg_info_group2,                         cfg_info_group3, cfg_info_group4, cfg_info_group5};     u8 cfg_info_len[] = { CFG_GROUP_LEN(cfg_info_group0),                           CFG_GROUP_LEN(cfg_info_group1),                           CFG_GROUP_LEN(cfg_info_group2),                           CFG_GROUP_LEN(cfg_info_group3),                           CFG_GROUP_LEN(cfg_info_group4),                           CFG_GROUP_LEN(cfg_info_group5)}; #if GTP_CHARGER_SWITCH  const u8 cfg_grp0_charger[] = GTP_CFG_GROUP0_CHARGER;  const u8 cfg_grp1_charger[] = GTP_CFG_GROUP1_CHARGER;  const u8 cfg_grp2_charger[] = GTP_CFG_GROUP2_CHARGER;  const u8 cfg_grp3_charger[] = GTP_CFG_GROUP3_CHARGER;  const u8 cfg_grp4_charger[] = GTP_CFG_GROUP4_CHARGER;  const u8 cfg_grp5_charger[] = GTP_CFG_GROUP5_CHARGER;  const u8 *cfgs_charger[] = {   cfg_grp0_charger, cfg_grp1_charger, cfg_grp2_charger,   cfg_grp3_charger, cfg_grp4_charger, cfg_grp5_charger  };  u8 cfg_lens_charger[] = {       CFG_GROUP_LEN(cfg_grp0_charger),       CFG_GROUP_LEN(cfg_grp1_charger),       CFG_GROUP_LEN(cfg_grp2_charger),       CFG_GROUP_LEN(cfg_grp3_charger),       CFG_GROUP_LEN(cfg_grp4_charger),       CFG_GROUP_LEN(cfg_grp5_charger)}; #endif

    GTP_DEBUG("Config Groups\' Lengths: %d, %d, %d, %d, %d, %d",         cfg_info_len[0], cfg_info_len[1], cfg_info_len[2], cfg_info_len[3],         cfg_info_len[4], cfg_info_len[5]);

    if ((!cfg_info_len[1]) && (!cfg_info_len[2]) &&         (!cfg_info_len[3]) && (!cfg_info_len[4]) &&         (!cfg_info_len[5]))     {         sensor_id = 0;     }     else     {     #if GTP_COMPATIBLE_MODE         if (CHIP_TYPE_GT9F == gtp_chip_type)         {             msleep(50);         }     #endif         ret = gtp_i2c_read_dbl_check(client, GTP_REG_SENSOR_ID, &sensor_id, 1);         if (SUCCESS == ret)         {             if (sensor_id >= 0x06)             {                 GTP_ERROR("Invalid sensor_id(0x%02X), No Config Sent!", sensor_id);                 pnl_init_error = 1;                 return -1;             }         }         else         {             GTP_ERROR("Failed to get sensor_id, No config sent!");             pnl_init_error = 1;             return -1;         }         GTP_INFO("Sensor_ID: %d", sensor_id);   if(sensor_id==2)   {    info += sprintf(info,"GT915L,");   info += sprintf(info,"O-film,");    info += sprintf(info, "%04x", tpd_info.vid);   }   else if(sensor_id==3)   {    info += sprintf(info,"GT915L,");   info += sprintf(info,"Yassy,");    info += sprintf(info, "%04x", tpd_info.vid);   }     }         cfg_len = cfg_info_len[sensor_id];         GTP_INFO("CTP_CONFIG_GROUP%d used, config length: %d", sensor_id, cfg_len);         if (cfg_len < GTP_CONFIG_MIN_LENGTH)     {         GTP_ERROR("CTP_CONFIG_GROUP%d is INVALID CONFIG GROUP! NO Config Sent! You need to check you header file CFG_GROUP section!", sensor_id);         pnl_init_error = 1;         return -1;     }     #if GTP_COMPATIBLE_MODE     if (CHIP_TYPE_GT9F != gtp_chip_type) #endif  {      ret = gtp_i2c_read_dbl_check(client, GTP_REG_CONFIG_DATA, &opr_buf[0], 1);         if (ret == SUCCESS)      {          GTP_DEBUG("CFG_CONFIG_GROUP%d Config Version: %d, 0x%02X; IC Config Version: %d, 0x%02X", sensor_id,                      send_cfg_buf[sensor_id][0], send_cfg_buf[sensor_id][0], opr_buf[0], opr_buf[0]);      flash_cfg_version = opr_buf[0];    drv_cfg_version = send_cfg_buf[sensor_id][0];       // backup  config version              if (flash_cfg_version < 90 && flash_cfg_version > drv_cfg_version) {              send_cfg_buf[sensor_id][0] = 0x00;          }      }      else      {          GTP_ERROR("Failed to get ic config version!No config sent!");          return -1;      }  }      memset(&config[GTP_ADDR_LENGTH], 0, GTP_CONFIG_MAX_LENGTH);     memcpy(&config[GTP_ADDR_LENGTH], send_cfg_buf[sensor_id], cfg_len);

#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);         if (GTP_INT_TRIGGER == 0)  //RISING     {         config[TRIGGER_LOC] &= 0xfe;     }     else if (GTP_INT_TRIGGER == 1)  //FALLING     {         config[TRIGGER_LOC] |= 0x01;     } #endif  // GTP_CUSTOM_CFG

 check_sum = 0;  for (i = GTP_ADDR_LENGTH; i < cfg_len; i++)  {   check_sum += config[i];  }  config[cfg_len] = (~check_sum) + 1;

#if GTP_CHARGER_SWITCH  GTP_DEBUG("Charger Config Groups Length: %d, %d, %d, %d, %d, %d", cfg_lens_charger[0],     cfg_lens_charger[1], cfg_lens_charger[2], cfg_lens_charger[3], cfg_lens_charger[4], cfg_lens_charger[5]);

 memset(&gtp_charger_config[GTP_ADDR_LENGTH], 0, GTP_CONFIG_MAX_LENGTH);  if (cfg_lens_charger[sensor_id] == cfg_len)   memcpy(&gtp_charger_config[GTP_ADDR_LENGTH], cfgs_charger[sensor_id], cfg_len);

#if GTP_CUSTOM_CFG  gtp_charger_config[RESOLUTION_LOC] = (u8) GTP_MAX_WIDTH;  gtp_charger_config[RESOLUTION_LOC + 1] = (u8) (GTP_MAX_WIDTH >> 8);  gtp_charger_config[RESOLUTION_LOC + 2] = (u8) GTP_MAX_HEIGHT;  gtp_charger_config[RESOLUTION_LOC + 3] = (u8) (GTP_MAX_HEIGHT >> 8);

 if (GTP_INT_TRIGGER == 0)  /* RISING  */   gtp_charger_config[TRIGGER_LOC] &= 0xfe;  else if (GTP_INT_TRIGGER == 1) /* FALLING */   gtp_charger_config[TRIGGER_LOC] |= 0x01; #endif /* END GTP_CUSTOM_CFG */  if (cfg_lens_charger[sensor_id] != cfg_len)   memset(&gtp_charger_config[GTP_ADDR_LENGTH], 0, GTP_CONFIG_MAX_LENGTH);     check_sum = 0;  for (i = GTP_ADDR_LENGTH; i < cfg_len; i++)  {   check_sum += gtp_charger_config[i];  }  gtp_charger_config[cfg_len] = (~check_sum) + 1;

#endif /* END GTP_CHARGER_SWITCH */      #else // DRIVER NOT SEND CONFIG     cfg_len = GTP_CONFIG_MAX_LENGTH;     ret = gtp_i2c_read(client, config, cfg_len + GTP_ADDR_LENGTH);     if (ret < 0)     {         GTP_ERROR("Read Config Failed, Using DEFAULT Resolution & INT Trigger!");         abs_x_max = GTP_MAX_WIDTH;         abs_y_max = GTP_MAX_HEIGHT;         int_type = GTP_INT_TRIGGER;     } #endif // GTP_DRIVER_SEND_CFG

    GTP_DEBUG_FUNC();     if ((abs_x_max == 0) && (abs_y_max == 0))     {         abs_x_max = (config[RESOLUTION_LOC + 1] << 8) + config[RESOLUTION_LOC];         abs_y_max = (config[RESOLUTION_LOC + 3] << 8) + config[RESOLUTION_LOC + 2];         int_type = (config[TRIGGER_LOC]) & 0x03;     }     #if GTP_COMPATIBLE_MODE     if (CHIP_TYPE_GT9F == gtp_chip_type)     {         u8 have_key = 0;         if (is_950)         {             driver_num = config[GTP_REG_MATRIX_DRVNUM - GTP_REG_CONFIG_DATA + 2];             sensor_num = config[GTP_REG_MATRIX_SENNUM - GTP_REG_CONFIG_DATA + 2];         }         else         {             driver_num = (config[CFG_LOC_DRVA_NUM]&0x1F) + (config[CFG_LOC_DRVB_NUM]&0x1F);             sensor_num = (config[CFG_LOC_SENS_NUM]&0x0F) + ((config[CFG_LOC_SENS_NUM]>>4)&0x0F);         }                 have_key = config[GTP_REG_HAVE_KEY - GTP_REG_CONFIG_DATA + 2] & 0x01;  // have key or not         if (1 == have_key)         {             driver_num--;         }                 GTP_INFO("Driver * Sensor: %d * %d(Key: %d), X_MAX = %d, Y_MAX = %d, TRIGGER = 0x%02x",             driver_num, sensor_num, have_key, abs_x_max,abs_y_max,int_type);     }     else #endif     { #if GTP_DRIVER_SEND_CFG         ret = gtp_send_cfg(client);         if (ret < 0)         {             GTP_ERROR("Send config error.");         } #if GTP_COMPATIBLE_MODE      if (CHIP_TYPE_GT9F != gtp_chip_type) #endif    {         /* for resume to send config */   if (flash_cfg_version < 90 && flash_cfg_version > drv_cfg_version) {            config[GTP_ADDR_LENGTH] = drv_cfg_version;          check_sum = 0;          for (i = GTP_ADDR_LENGTH; i < cfg_len; i++)          {              check_sum += config[i];          }          config[cfg_len] = (~check_sum) + 1;   }    } #endif         GTP_INFO("X_MAX = %d, Y_MAX = %d, TRIGGER = 0x%02x",             abs_x_max,abs_y_max,int_type);     }         msleep(10);     return 0; }

/******************************************************* Function:     GTP initialize function.

Input:     client: i2c client private struct.

Output:     Executive outcomes.0---succeed. *******************************************************/ static s32 gtp_cover_panel(struct i2c_client *client) {     s32 ret = 0;

#if GTP_DRIVER_SEND_CFG     s32 i;     u8 check_sum = 0;     u8 opr_buf[16];     u8 sensor_id = 0;   u8 drv_cfg_version;   u8 flash_cfg_version;

    u8 cfg_cover_info_group0[] = CTP_CFG_COVER_GROUP0;     u8 cfg_cover_info_group1[] = CTP_CFG_COVER_GROUP1;     u8 cfg_cover_info_group2[] = CTP_CFG_COVER_GROUP2;     u8 cfg_cover_info_group3[] = CTP_CFG_COVER_GROUP3;     u8 cfg_cover_info_group4[] = CTP_CFG_COVER_GROUP4;     u8 cfg_cover_info_group5[] = CTP_CFG_COVER_GROUP5;     u8 *send_cover_cfg_buf[] = {cfg_cover_info_group0, cfg_cover_info_group1, cfg_cover_info_group2,                         cfg_cover_info_group3, cfg_cover_info_group4, cfg_cover_info_group5};     u8 cfg_cover_info_len[] = { CFG_GROUP_LEN(cfg_cover_info_group0),                           CFG_GROUP_LEN(cfg_cover_info_group1),                           CFG_GROUP_LEN(cfg_cover_info_group2),                           CFG_GROUP_LEN(cfg_cover_info_group3),                           CFG_GROUP_LEN(cfg_cover_info_group4),                           CFG_GROUP_LEN(cfg_cover_info_group5)}; #if GTP_CHARGER_SWITCH  const u8 cfg_cover_grp0_charger[] = GTP_CFG_COVER_GROUP0_CHARGER;  const u8 cfg_cover_grp1_charger[] = GTP_CFG_COVER_GROUP1_CHARGER;  const u8 cfg_cover_grp2_charger[] = GTP_CFG_COVER_GROUP2_CHARGER;  const u8 cfg_cover_grp3_charger[] = GTP_CFG_COVER_GROUP3_CHARGER;  const u8 cfg_cover_grp4_charger[] = GTP_CFG_COVER_GROUP4_CHARGER;  const u8 cfg_cover_grp5_charger[] = GTP_CFG_COVER_GROUP5_CHARGER;  const u8 *cfgs_cover_charger[] = {   cfg_cover_grp0_charger, cfg_cover_grp1_charger, cfg_cover_grp2_charger,   cfg_cover_grp3_charger, cfg_cover_grp4_charger, cfg_cover_grp5_charger  };  u8 cfg_cover_lens_charger[] = {       CFG_GROUP_LEN(cfg_cover_grp0_charger),       CFG_GROUP_LEN(cfg_cover_grp1_charger),       CFG_GROUP_LEN(cfg_cover_grp2_charger),       CFG_GROUP_LEN(cfg_cover_grp3_charger),       CFG_GROUP_LEN(cfg_cover_grp4_charger),       CFG_GROUP_LEN(cfg_cover_grp5_charger)}; #endif

    GTP_DEBUG("Config Groups\' Lengths: %d, %d, %d, %d, %d, %d",         cfg_cover_info_len[0], cfg_cover_info_len[1], cfg_cover_info_len[2], cfg_cover_info_len[3],         cfg_cover_info_len[4], cfg_cover_info_len[5]);

    if ((!cfg_cover_info_len[1]) && (!cfg_cover_info_len[2]) &&         (!cfg_cover_info_len[3]) && (!cfg_cover_info_len[4]) &&         (!cfg_cover_info_len[5]))     {         sensor_id = 0;     }     else     {     #if GTP_COMPATIBLE_MODE         if (CHIP_TYPE_GT9F == gtp_chip_type)         {             msleep(50);         }     #endif         ret = gtp_i2c_read_dbl_check(client, GTP_REG_SENSOR_ID, &sensor_id, 1);         if (SUCCESS == ret)         {             if (sensor_id >= 0x06)             {                 GTP_ERROR("Invalid sensor_id(0x%02X), No Config Sent!", sensor_id);                 pnl_cover_init_error = 1;                 return -1;             }         }         else         {             GTP_ERROR("Failed to get sensor_id, No config sent!");             pnl_cover_init_error = 1;             return -1;         }         GTP_INFO("Sensor_ID: %d", sensor_id);     }         cfg_cover_len = cfg_cover_info_len[sensor_id];         GTP_INFO("CTP_CONFIG_GROUP%d used, config length: %d", sensor_id, cfg_cover_len);         if (cfg_cover_len < GTP_CONFIG_MIN_LENGTH)     {         GTP_ERROR("CTP_CONFIG_GROUP%d is INVALID CONFIG GROUP! NO Config Sent! You need to check you header file CFG_GROUP section!", sensor_id);         pnl_cover_init_error = 1;         return -1;     }     #if GTP_COMPATIBLE_MODE     if (CHIP_TYPE_GT9F != gtp_chip_type) #endif  {      ret = gtp_i2c_read_dbl_check(client, GTP_REG_CONFIG_DATA, &opr_buf[0], 1);         if (ret == SUCCESS)      {          GTP_DEBUG("CFG_CONFIG_GROUP%d Config Version: %d, 0x%02X; IC Config Version: %d, 0x%02X", sensor_id,                      send_cover_cfg_buf[sensor_id][0], send_cover_cfg_buf[sensor_id][0], opr_buf[0], opr_buf[0]);      flash_cfg_version = opr_buf[0];    drv_cfg_version = send_cover_cfg_buf[sensor_id][0];       // backup  config version              if (flash_cfg_version < 90 && flash_cfg_version > drv_cfg_version) {              send_cover_cfg_buf[sensor_id][0] = 0x00;          }      }      else      {          GTP_ERROR("Failed to get ic config version!No config sent!");          return -1;      }  }      memset(&config_cover[GTP_ADDR_LENGTH], 0, GTP_CONFIG_MAX_LENGTH);     memcpy(&config_cover[GTP_ADDR_LENGTH], send_cover_cfg_buf[sensor_id], cfg_cover_len);

#if GTP_CUSTOM_CFG     config_cover[RESOLUTION_LOC]     = (u8)GTP_MAX_WIDTH;     config_cover[RESOLUTION_LOC + 1] = (u8)(GTP_MAX_WIDTH>>8);     config_cover[RESOLUTION_LOC + 2] = (u8)GTP_MAX_HEIGHT;     config_cover[RESOLUTION_LOC + 3] = (u8)(GTP_MAX_HEIGHT>>8);         if (GTP_INT_TRIGGER == 0)  //RISING     {         config_cover[TRIGGER_LOC] &= 0xfe;     }     else if (GTP_INT_TRIGGER == 1)  //FALLING     {         config_cover[TRIGGER_LOC] |= 0x01;     } #endif  // GTP_CUSTOM_CFG

 check_sum = 0;  for (i = GTP_ADDR_LENGTH; i < cfg_cover_len; i++)  {   check_sum += config_cover[i];  }  config_cover[cfg_cover_len] = (~check_sum) + 1;

#if GTP_CHARGER_SWITCH  GTP_DEBUG("Charger Config Groups Length: %d, %d, %d, %d, %d, %d", cfg_cover_lens_charger[0],     cfg_cover_lens_charger[1], cfg_cover_lens_charger[2], cfg_cover_lens_charger[3], cfg_cover_lens_charger[4], cfg_cover_lens_charger[5]);

 memset(&gtp_charger_config_cover[GTP_ADDR_LENGTH], 0, GTP_CONFIG_MAX_LENGTH);  if (cfg_cover_lens_charger[sensor_id] == cfg_cover_len)   memcpy(&gtp_charger_config_cover[GTP_ADDR_LENGTH], cfgs_cover_charger[sensor_id], cfg_cover_len);

#if GTP_CUSTOM_CFG  gtp_charger_config_cover[RESOLUTION_LOC] = (u8) GTP_MAX_WIDTH;  gtp_charger_config_cover[RESOLUTION_LOC + 1] = (u8) (GTP_MAX_WIDTH >> 8);  gtp_charger_config_cover[RESOLUTION_LOC + 2] = (u8) GTP_MAX_HEIGHT;  gtp_charger_config_cover[RESOLUTION_LOC + 3] = (u8) (GTP_MAX_HEIGHT >> 8);

 if (GTP_INT_TRIGGER == 0)  /* RISING  */   gtp_charger_config_cover[TRIGGER_LOC] &= 0xfe;  else if (GTP_INT_TRIGGER == 1) /* FALLING */   gtp_charger_config_cover[TRIGGER_LOC] |= 0x01; #endif /* END GTP_CUSTOM_CFG */  if (cfg_cover_lens_charger[sensor_id] != cfg_cover_len)   memset(&gtp_charger_config_cover[GTP_ADDR_LENGTH], 0, GTP_CONFIG_MAX_LENGTH);     check_sum = 0;  for (i = GTP_ADDR_LENGTH; i < cfg_cover_len; i++)  {   check_sum += gtp_charger_config_cover[i];  }  gtp_charger_config_cover[cfg_cover_len] = (~check_sum) + 1;

#endif /* END GTP_CHARGER_SWITCH */      #else // DRIVER NOT SEND CONFIG     cfg_cover_len = GTP_CONFIG_MAX_LENGTH;     ret = gtp_i2c_read(client, config_cover, cfg_cover_len + GTP_ADDR_LENGTH);     if (ret < 0)     {         GTP_ERROR("Read Config Failed, Using DEFAULT Resolution & INT Trigger!");         abs_x_max = GTP_MAX_WIDTH;         abs_y_max = GTP_MAX_HEIGHT;         int_type = GTP_INT_TRIGGER;     } #endif // GTP_DRIVER_SEND_CFG

    GTP_DEBUG_FUNC();     if ((abs_x_max == 0) && (abs_y_max == 0))     {         abs_x_max = (config_cover[RESOLUTION_LOC + 1] << 8) + config_cover[RESOLUTION_LOC];         abs_y_max = (config_cover[RESOLUTION_LOC + 3] << 8) + config_cover[RESOLUTION_LOC + 2];         int_type = (config_cover[TRIGGER_LOC]) & 0x03;     }     #if GTP_COMPATIBLE_MODE     if (CHIP_TYPE_GT9F == gtp_chip_type)     {         u8 have_key = 0;         if (is_950)         {             driver_num_cover = config_cover[GTP_REG_MATRIX_DRVNUM - GTP_REG_CONFIG_DATA + 2];             sensor_num_cover = config_cover[GTP_REG_MATRIX_SENNUM - GTP_REG_CONFIG_DATA + 2];         }         else         {             driver_num_cover = (config_cover[CFG_LOC_DRVA_NUM]&0x1F) + (config_cover[CFG_LOC_DRVB_NUM]&0x1F);             sensor_num_cover = (config_cover[CFG_LOC_SENS_NUM]&0x0F) + ((config_cover[CFG_LOC_SENS_NUM]>>4)&0x0F);         }                 have_key = config_cover[GTP_REG_HAVE_KEY - GTP_REG_CONFIG_DATA + 2] & 0x01;  // have key or not         if (1 == have_key)         {             driver_num_cover--;         }                 GTP_INFO("Driver * Sensor: %d * %d(Key: %d), X_MAX = %d, Y_MAX = %d, TRIGGER = 0x%02x",             driver_num_cover, sensor_num_cover, have_key, abs_x_max,abs_y_max,int_type);     }     else #endif     { #if GTP_DRIVER_SEND_CFG #if GTP_COMPATIBLE_MODE      if (CHIP_TYPE_GT9F != gtp_chip_type) #endif    {         /* for resume to send config */   if (flash_cfg_version < 90 && flash_cfg_version > drv_cfg_version) {            config_cover[GTP_ADDR_LENGTH] = drv_cfg_version;          check_sum = 0;          for (i = GTP_ADDR_LENGTH; i < cfg_cover_len; i++)          {              check_sum += config_cover[i];          }          config_cover[cfg_cover_len] = (~check_sum) + 1;   }    } #endif         GTP_INFO("X_MAX = %d, Y_MAX = %d, TRIGGER = 0x%02x",             abs_x_max,abs_y_max,int_type);     }         msleep(10);     return 0; }

static s8 gtp_i2c_test(struct i2c_client *client) {

    u8 retry = 0;     s8 ret = -1;     u32 hw_info = 0;

    GTP_DEBUG_FUNC();

    while (retry++ < 5)     {         ret = i2c_read_bytes(client, GTP_REG_HW_INFO, (u8 *)&hw_info, sizeof(hw_info));

        if ((!ret) && (hw_info == 0x00900600))              //20121212         {             return ret;         }

        GTP_ERROR("GTP_REG_HW_INFO : %08X", hw_info);         GTP_ERROR("GTP i2c test failed time %d.", retry);         msleep(10);     }

    return -1; }

 

/******************************************************* Function:     Set INT pin  as input for FW sync.

Note:   If the INT is high, It means there is pull up resistor attached on the INT pin.   Pull low the INT pin manaully for FW sync. *******************************************************/ void gtp_int_sync(s32 ms) {     GTP_GPIO_OUTPUT(GTP_INT_PORT, 0);     msleep(ms);     GTP_GPIO_AS_INT(GTP_INT_PORT); }

void gtp_reset_guitar(struct i2c_client *client, s32 ms) {     GTP_INFO("GTP RESET!\n");     GTP_GPIO_OUTPUT(GTP_RST_PORT, 0);     msleep(ms);     GTP_GPIO_OUTPUT(GTP_INT_PORT, client->addr == 0x14);

    msleep(2);     GTP_GPIO_OUTPUT(GTP_RST_PORT, 1);

    msleep(6);                      //must >= 6ms

#if GTP_COMPATIBLE_MODE     if (CHIP_TYPE_GT9F == gtp_chip_type)     {         return;     } #endif

    gtp_int_sync(50); #if GTP_ESD_PROTECT     gtp_init_ext_watchdog(i2c_client_point); #endif }

static int tpd_power_on(struct i2c_client *client) {     int ret = 0;     int reset_count = 0;

reset_proc:     GTP_GPIO_OUTPUT(GTP_RST_PORT, 0);       GTP_GPIO_OUTPUT(GTP_INT_PORT, 0);     msleep(10);

#ifdef MT6573     // power on CTP     mt_set_gpio_mode(GPIO_CTP_EN_PIN, GPIO_CTP_EN_PIN_M_GPIO);     mt_set_gpio_dir(GPIO_CTP_EN_PIN, GPIO_DIR_OUT);     mt_set_gpio_out(GPIO_CTP_EN_PIN, GPIO_OUT_ONE);

#else   // ( defined(MT6575) || defined(MT6577) || defined(MT6589) )

    #ifdef TPD_POWER_SOURCE_CUSTOM                                   hwPowerOn(TPD_POWER_SOURCE_CUSTOM, VOL_2800, "TP");        #else         hwPowerOn(MT65XX_POWER_LDO_VGP2, VOL_2800, "TP");     #endif     #ifdef TPD_POWER_SOURCE_1800         hwPowerOn(TPD_POWER_SOURCE_1800, VOL_1800, "TP");     #endif

#endif

    gtp_reset_guitar(client, 20);

#if GTP_COMPATIBLE_MODE     gtp_get_chip_type(client);         if (CHIP_TYPE_GT9F == gtp_chip_type)     {         ret = gup_fw_download_proc(NULL, GTP_FL_FW_BURN);             if(FAIL == ret)         {             GTP_ERROR("[tpd_power_on]Download fw failed.");             if(reset_count++ < TPD_MAX_RESET_COUNT)             {                 goto reset_proc;             }             else             {                 return -1;             }         }                 ret = gtp_fw_startup(client);         if(FAIL == ret)         {             GTP_ERROR("[tpd_power_on]Startup fw failed.");             if(reset_count++ < TPD_MAX_RESET_COUNT)             {                 goto reset_proc;             }             else             {                 return -1;             }         }     }     else  #endif     {         ret = gtp_i2c_test(client);             if (ret < 0)         {             GTP_ERROR("I2C communication ERROR!");                 if (reset_count < TPD_MAX_RESET_COUNT)             {                 reset_count++;                 goto reset_proc;             }         }     }     return ret; }

void gtp_irq_enable(void) {  if(irq_flag==0){   irq_flag++; #ifdef CONFIG_OF_TOUCH   enable_irq(touch_irq); #else   mt_eint_unmask(CUST_EINT_TOUCH_PANEL_NUM); #endif  }else{   GTP_INFO("Touch Eint already enabled!");  }  //GTP_INFO("Enable irq_flag=%d",irq_flag);

} void gtp_irq_disable(void) {  if(irq_flag==1){   irq_flag--; #ifdef CONFIG_OF_TOUCH   disable_irq(touch_irq); #else   mt_eint_mask(CUST_EINT_TOUCH_PANEL_NUM); #endif  }else{   GTP_INFO("Touch Eint already disabled!");  }  //GTP_INFO("Disable irq_flag=%d",irq_flag); }

#ifdef CONFIG_OF_TOUCH static int tpd_irq_registration(void) {  struct device_node *node = NULL;  int ret = 0;  u32 ints[2] = {0,0};  GTP_INFO("Device Tree Tpd_irq_registration!");    node = of_find_compatible_node(NULL, NULL, "mediatek, TOUCH_PANEL-eint");  if(node){   of_property_read_u32_array(node , "debounce", ints, ARRAY_SIZE(ints));   gpio_set_debounce(ints[0], ints[1]);

  touch_irq = irq_of_parse_and_map(node, 0);   GTP_INFO("Device gtp_int_type = %d!", int_type);   if (!int_type) //EINTF_TRIGGER   {    ret = request_irq(touch_irq, (irq_handler_t)tpd_eint_interrupt_handler, EINTF_TRIGGER_RISING, "TOUCH_PANEL-eint", NULL);             //gtp_eint_trigger_type = EINTF_TRIGGER_RISING;    if(ret > 0){        ret = -1;        GTP_ERROR("tpd request_irq IRQ LINE NOT AVAILABLE!.");    }   }   else   {    ret = request_irq(touch_irq, (irq_handler_t)tpd_eint_interrupt_handler, EINTF_TRIGGER_FALLING, "TOUCH_PANEL-eint", NULL);             //gtp_eint_trigger_type = EINTF_TRIGGER_FALLING;    if(ret > 0){        ret = -1;        GTP_ERROR("tpd request_irq IRQ LINE NOT AVAILABLE!.");    }   }  }else{   GTP_ERROR("tpd request_irq can not find touch eint device node!.");   ret = -1;  }  GTP_INFO("[%s]irq:%d, debounce:%d-%d:", __FUNCTION__, touch_irq, ints[0], ints[1]);  return ret; } #endif

//**************** For GT9XXF Start ********************// #if GTP_COMPATIBLE_MODE

void gtp_get_chip_type(struct i2c_client *client) {     u8 opr_buf[10] = {0x00};     s32 ret = 0;         msleep(10);         ret = gtp_i2c_read_dbl_check(client, GTP_REG_CHIP_TYPE, opr_buf, 10);         if (FAIL == ret)     {         GTP_ERROR("Failed to get chip-type, set chip type default: GOODIX_GT9");         gtp_chip_type = CHIP_TYPE_GT9;         return;     }         if (!memcmp(opr_buf, "GOODIX_GT9", 10))     {         gtp_chip_type = CHIP_TYPE_GT9;     }     else // GT9XXF     {         gtp_chip_type = CHIP_TYPE_GT9F;     }     GTP_INFO("Chip Type: %s", (gtp_chip_type == CHIP_TYPE_GT9) ? "GOODIX_GT9" : "GOODIX_GT9F"); }

static u8 gtp_bak_ref_proc(struct i2c_client *client, u8 mode) {     s32 i = 0;     s32 j = 0;     s32 ret = 0;     struct file *flp = NULL;     u8 *refp = NULL;     u32 ref_len = 0;     u32 ref_seg_len = 0;     s32 ref_grps = 0;     s32 ref_chksum = 0;     u16 tmp = 0;         GTP_DEBUG("[gtp_bak_ref_proc]Driver:%d,Sensor:%d.", driver_num, sensor_num);

    //check file-system mounted     GTP_DEBUG("[gtp_bak_ref_proc]Waiting for FS %d", gtp_ref_retries);            if (gup_check_fs_mounted("/data") == FAIL)            {         GTP_DEBUG("[gtp_bak_ref_proc]/data not mounted");         if(gtp_ref_retries++ < GTP_CHK_FS_MNT_MAX)         {             return FAIL;         }     }     else     {         GTP_DEBUG("[gtp_bak_ref_proc]/data mounted !!!!");     }         if (is_950)     {         ref_seg_len = (driver_num * (sensor_num - 1) + 2) * 2;         ref_grps = 6;         ref_len =  ref_seg_len * 6;  // for GT950, backup-reference for six segments     }     else     {         ref_len = driver_num*(sensor_num-2)*2 + 4;         ref_seg_len = ref_len;         ref_grps = 1;     }         refp = (u8 *)kzalloc(ref_len, GFP_KERNEL);     if(refp == NULL)     {         GTP_ERROR("Failed to allocate memory for reference buffer!");         return FAIL;     }     memset(refp, 0, ref_len);         //get ref file data     flp = filp_open(GTP_BAK_REF_PATH, O_RDWR | O_CREAT, 0666);     if (IS_ERR(flp))     {         GTP_ERROR("Failed to open/create %s.", GTP_BAK_REF_PATH);         if (GTP_BAK_REF_SEND == mode)         {             goto default_bak_ref;         }         else         {             goto exit_ref_proc;         }     }         switch (mode)     {     case GTP_BAK_REF_SEND:         {             flp->f_op->llseek(flp, 0, SEEK_SET);             ret = flp->f_op->read(flp, (char *)refp, ref_len, &flp->f_pos);             if(ret < 0)             {                 GTP_ERROR("Read ref file failed, send default bak ref.");                 goto default_bak_ref;             }             //checksum ref file             for (j = 0; j < ref_grps; ++j)             {                 ref_chksum = 0;                 for(i=0; i<ref_seg_len-2; i+=2)                 {                     ref_chksum += ((refp[i + j * ref_seg_len]<<8) + refp[i + 1 + j * ref_seg_len]);                 }                             GTP_DEBUG("Reference chksum:0x%04X", ref_chksum&0xFF);                 tmp = ref_chksum + (refp[ref_seg_len + j * ref_seg_len -2]<<8) + refp[ref_seg_len + j * ref_seg_len -1];                 if(1 != tmp)                 {                     GTP_DEBUG("Invalid checksum for reference, reset reference.");                     memset(&refp[j * ref_seg_len], 0, ref_seg_len);                     refp[ref_seg_len - 1 + j * ref_seg_len] = 0x01;                 }                 else                 {                     if (j == (ref_grps - 1))                     {                         GTP_INFO("Reference data in %s used.", GTP_BAK_REF_PATH);                     }                 }                           }             ret = i2c_write_bytes(client, GTP_REG_BAK_REF, refp, ref_len);             if(-1 == ret)             {                 GTP_ERROR("Write ref i2c error.");                 ret = FAIL;                 goto exit_ref_proc;             }         }         break;             case GTP_BAK_REF_STORE:         {             ret = i2c_read_bytes(client, GTP_REG_BAK_REF, refp, ref_len);             if(-1 == ret)             {                 GTP_ERROR("Read ref i2c error.");                 ret = FAIL;                 goto exit_ref_proc;             }             flp->f_op->llseek(flp, 0, SEEK_SET);             flp->f_op->write(flp, (char *)refp, ref_len, &flp->f_pos);         }         break;             default:         GTP_ERROR("Invalid Argument(%d) for backup reference", mode);         ret = FAIL;         goto exit_ref_proc;     }         ret = SUCCESS;     goto exit_ref_proc;

default_bak_ref:     for (j = 0; j < ref_grps; ++j)     {         memset(&refp[j * ref_seg_len], 0, ref_seg_len);         refp[j * ref_seg_len + ref_seg_len - 1] = 0x01;  // checksum = 1     }     ret = i2c_write_bytes(client, GTP_REG_BAK_REF, refp, ref_len);     if (flp && !IS_ERR(flp))     {         GTP_INFO("Write backup-reference data into %s", GTP_BAK_REF_PATH);         flp->f_op->llseek(flp, 0, SEEK_SET);         flp->f_op->write(flp, (char*)refp, ref_len, &flp->f_pos);     }     if (ret < 0)     {         GTP_ERROR("Failed to load the default backup reference");         ret = FAIL;     }     else     {         ret = SUCCESS;     } exit_ref_proc:     if (refp)     {         kfree(refp);     }     if (flp && !IS_ERR(flp))     {         filp_close(flp, NULL);     }     return ret; }

u8 gtp_fw_startup(struct i2c_client *client) {     u8 wr_buf[4];     s32 ret = 0;         //init sw WDT     wr_buf[0] = 0xAA;     ret = i2c_write_bytes(client, 0x8041, wr_buf, 1);     if (ret < 0)     {         GTP_ERROR("I2C error to firmware startup.");         return FAIL;     }     //release SS51 & DSP     wr_buf[0] = 0x00;     i2c_write_bytes(client, 0x4180, wr_buf, 1);         //int sync     gtp_int_sync(25);         //check fw run status     i2c_read_bytes(client, 0x8041, wr_buf, 1);     if(0xAA == wr_buf[0])     {         GTP_ERROR("IC works abnormally,startup failed.");         return FAIL;     }     else     {         GTP_DEBUG("IC works normally,Startup success.");         wr_buf[0] = 0xAA;         i2c_write_bytes(client, 0x8041, wr_buf, 1);         return SUCCESS;     } }

static void gtp_recovery_reset(struct i2c_client *client) { #if GTP_ESD_PROTECT     gtp_esd_switch(client, SWITCH_OFF); #endif     force_reset_guitar(); #if GTP_ESD_PROTECT     gtp_esd_switch(client, SWITCH_ON); #endif }

static u8 gtp_check_clk_legality(u8 *p_clk_buf) {     u8 i = 0;     u8 clk_chksum = p_clk_buf[5];         for(i = 0; i < 5; i++)     {         if((p_clk_buf[i] < 50) || (p_clk_buf[i] > 120) ||             (p_clk_buf[i] != p_clk_buf[0]))         {             break;         }         clk_chksum += p_clk_buf[i];     }         if((i == 5) && (clk_chksum == 0))     {         GTP_DEBUG("Valid main clock data.");         return SUCCESS;     }     GTP_ERROR("Invalid main clock data.");     return FAIL; }

static u8 gtp_main_clk_proc(struct i2c_client *client) {     s32 ret = 0;     u8  i = 0;     u8  clk_cal_result = 0;     u8  clk_chksum = 0;     u8  gtp_clk_buf[6] = {0};     struct file *flp = NULL;         GTP_DEBUG("[gtp_main_clk_proc]Waiting for FS %d", gtp_ref_retries);            if (gup_check_fs_mounted("/data") == FAIL)            {                    GTP_DEBUG("[gtp_main_clk_proc]/data not mounted");         if(gtp_clk_retries++ < GTP_CHK_FS_MNT_MAX)         {             return FAIL;         }         else         {             GTP_ERROR("[gtp_main_clk_proc]Wait for file system timeout,need cal clk");         }     }     else     {         GTP_DEBUG("[gtp_main_clk_proc]/data mounted !!!!");         flp = filp_open(GTP_MAIN_CLK_PATH, O_RDWR | O_CREAT, 0666);         if (!IS_ERR(flp))         {             flp->f_op->llseek(flp, 0, SEEK_SET);             ret = flp->f_op->read(flp, (char *)gtp_clk_buf, 6, &flp->f_pos);             if(ret > 0)             {                 ret = gtp_check_clk_legality(gtp_clk_buf);                 if(SUCCESS == ret)                 {                         GTP_DEBUG("[gtp_main_clk_proc]Open & read & check clk file success.");                     goto send_main_clk;                 }             }         }         GTP_ERROR("[gtp_main_clk_proc]Check clk file failed,need cal clk");     }         //cal clk #if GTP_ESD_PROTECT     gtp_esd_switch(client, SWITCH_OFF); #endif     clk_cal_result = gup_clk_calibration();     force_reset_guitar();     GTP_DEBUG("&&&&&&&&&&clk cal result:%d", clk_cal_result);     #if GTP_ESD_PROTECT     gtp_esd_switch(client, SWITCH_ON); #endif 

    if(clk_cal_result < 50 || clk_cal_result > 120)     {         GTP_ERROR("Invalid main clock: %d", clk_cal_result);         ret = FAIL;         goto exit_clk_proc;     }         for(i = 0;i < 5; i++)     {         gtp_clk_buf[i] = clk_cal_result;         clk_chksum += gtp_clk_buf[i];     }     gtp_clk_buf[5] = 0 - clk_chksum;     send_main_clk:         ret = i2c_write_bytes(client, 0x8020, gtp_clk_buf, 6);         if (flp && !IS_ERR(flp))     {         flp->f_op->llseek(flp, 0, SEEK_SET);         flp->f_op->write(flp, (char *)gtp_clk_buf, 6, &flp->f_pos);     }         if(-1 == ret)     {         GTP_ERROR("[gtp_main_clk_proc]send main clk i2c error!");         ret = FAIL;     }     else     {         ret = SUCCESS;     }     exit_clk_proc:     if (flp && !IS_ERR(flp))     {         filp_close(flp, NULL);     }     return ret; }

#endif //************* For GT9XXF End **********************//

#if GTP_WITH_PEN static void gtp_pen_init(void) {     s32 ret = 0;         pen_dev = input_allocate_device();     if (pen_dev == NULL)     {         GTP_ERROR("Failed to allocate input device for pen/stylus.");         return;     }         pen_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) ;     pen_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);         set_bit(BTN_TOOL_PEN, pen_dev->keybit);     set_bit(INPUT_PROP_DIRECT, pen_dev->propbit);     //set_bit(INPUT_PROP_POINTER, pen_dev->propbit);     #if GTP_PEN_HAVE_BUTTON     input_set_capability(pen_dev, EV_KEY, BTN_STYLUS);     input_set_capability(pen_dev, EV_KEY, BTN_STYLUS2); #endif

    input_set_abs_params(pen_dev, ABS_MT_POSITION_X, 0, TPD_RES_X, 0, 0);     input_set_abs_params(pen_dev, ABS_MT_POSITION_Y, 0, TPD_RES_Y, 0, 0);     input_set_abs_params(pen_dev, ABS_MT_PRESSURE, 0, 255, 0, 0);     input_set_abs_params(pen_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);     input_set_abs_params(pen_dev, ABS_MT_TRACKING_ID, 0, 255, 0, 0);         pen_dev->name = "mtk-pen";     pen_dev->phys = "input/ts";     pen_dev->id.bustype = BUS_I2C;         ret = input_register_device(pen_dev);     if (ret)     {         GTP_ERROR("Register %s input device failed", pen_dev->name);         return;     } }

static void gtp_pen_down(s32 x, s32 y, s32 size, s32 id) {     input_report_key(pen_dev, BTN_TOOL_PEN, 1);     input_report_key(pen_dev, BTN_TOUCH, 1);     input_report_abs(pen_dev, ABS_MT_POSITION_X, x);     input_report_abs(pen_dev, ABS_MT_POSITION_Y, y);     if ((!size) && (!id))     {         input_report_abs(pen_dev, ABS_MT_PRESSURE, 100);         input_report_abs(pen_dev, ABS_MT_TOUCH_MAJOR, 100);     }     else     {         input_report_abs(pen_dev, ABS_MT_PRESSURE, size);         input_report_abs(pen_dev, ABS_MT_TOUCH_MAJOR, size);         input_report_abs(pen_dev, ABS_MT_TRACKING_ID, id);     }     input_mt_sync(pen_dev); }

static void gtp_pen_up(void) {     input_report_key(pen_dev, BTN_TOOL_PEN, 0);     input_report_key(pen_dev, BTN_TOUCH, 0); } #endif

static s32 tpd_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) {     s32 err = 0;     s32 ret = 0;

    u16 version_info;   #if GTP_HAVE_TOUCH_KEY     s32 idx = 0; #endif #ifdef TPD_PROXIMITY     struct hwmsen_object obj_ps; #endif

    if (RECOVERY_BOOT == get_boot_mode())             return 0;

    i2c_client_point = client;     ret = tpd_power_on(client);

    if (ret < 0)     {         GTP_ERROR("I2C communication ERROR!");     }     //#ifdef VELOCITY_CUSTOM #if 0     if ((err = misc_register(&tpd_misc_device)))     {         printk("mtk_tpd: tpd_misc_device register failed\n");     }

#endif     ret = gtp_read_version(client, &version_info);

    if (ret < 0)     {         GTP_ERROR("Read version failed.");     }            ret = gtp_init_panel(client);

    if (ret < 0)     {         GTP_ERROR("GTP init panel failed.");     }   #if GTP_COVER_CONTROL     ret = gtp_cover_panel(client);

    if (ret < 0)     {         GTP_ERROR("GTP cover panel failed.");     } #endif         // Create proc file system     gt91xx_config_proc = proc_create(GT91XX_CONFIG_PROC_FILE, 0644, NULL, &config_proc_ops);     if (gt91xx_config_proc == NULL)     {         GTP_ERROR("create_proc_entry %s failed\n", GT91XX_CONFIG_PROC_FILE);     }     else     {         GTP_INFO("create proc entry %s success", GT91XX_CONFIG_PROC_FILE);     }  //add by chen for MX gesture    mx_tsp=root_device_register("mx_tsp");

 err = sysfs_create_group(&mx_tsp->kobj,&gesture_attribute_group);  if (err < 0)  {     GTP_ERROR("unable to create gesture attribute file\n");  }

 //add end

#if GTP_COVER_CONTROL  err =register_cover_notifier(&cover_notifier1);    if (err)    {         GTP_ERROR("register cover_notifier1 error\n");    } #endif

#if GTP_P_GESTURE_CONTROL  err =register_cover_notifier(&gesture_notifier1);    if (err)    {         GTP_ERROR("register gesture_notifier1 error\n");    } #endif

#if GTP_CREATE_WR_NODE     init_wr_node(client); #endif

    thread = kthread_run(touch_event_handler, 0, TPD_DEVICE);

    if (IS_ERR(thread))     {         err = PTR_ERR(thread);         GTP_INFO(TPD_DEVICE " failed to create kernel thread: %d\n", err);     }         #if GTP_HAVE_TOUCH_KEY

    for (idx = 0; idx < GTP_MAX_KEY_NUM; idx++)     {         input_set_capability(tpd->dev, EV_KEY, touch_key_array[idx]);     }

#endif #if GTP_GESTURE_WAKEUP //    input_set_capability(tpd->dev, EV_KEY, KEY_POWER);     input_set_capability(tpd->dev, EV_KEY, KEY_GESTURE); #endif     #if GTP_WITH_PEN     gtp_pen_init(); #endif     // set INT mode     mt_set_gpio_mode(GPIO_CTP_EINT_PIN, GPIO_CTP_EINT_PIN_M_EINT);     mt_set_gpio_dir(GPIO_CTP_EINT_PIN, GPIO_DIR_IN);     mt_set_gpio_pull_enable(GPIO_CTP_EINT_PIN, GPIO_PULL_DISABLE);

    msleep(50);

#ifdef CONFIG_OF_TOUCH  /* EINT device tree, default EINT enable */  tpd_irq_registration(); #else

#ifdef MT6572     if (!int_type)  //EINTF_TRIGGER     {         mt_eint_registration(CUST_EINT_TOUCH_PANEL_NUM, EINTF_TRIGGER_RISING, tpd_eint_interrupt_handler, 1);     }     else     {         mt_eint_registration(CUST_EINT_TOUCH_PANEL_NUM, EINTF_TRIGGER_FALLING, tpd_eint_interrupt_handler, 1);     }     #else     mt65xx_eint_set_sens(CUST_EINT_TOUCH_PANEL_NUM, CUST_EINT_TOUCH_PANEL_SENSITIVE);     mt65xx_eint_set_hw_debounce(CUST_EINT_TOUCH_PANEL_NUM, CUST_EINT_TOUCH_PANEL_DEBOUNCE_CN);

    if (!int_type)     {         mt65xx_eint_registration(CUST_EINT_TOUCH_PANEL_NUM, CUST_EINT_TOUCH_PANEL_DEBOUNCE_EN, CUST_EINT_POLARITY_HIGH, tpd_eint_interrupt_handler, 1);     }     else     {         mt65xx_eint_registration(CUST_EINT_TOUCH_PANEL_NUM, CUST_EINT_TOUCH_PANEL_DEBOUNCE_EN, CUST_EINT_POLARITY_LOW, tpd_eint_interrupt_handler, 1);     } #endif #endif   gtp_irq_enable(); #if GTP_ESD_PROTECT     gtp_esd_switch(client, SWITCH_ON); #endif

#if GTP_AUTO_UPDATE     ret = gup_init_update_proc(client);

    if (ret < 0)     {         GTP_ERROR("Create update thread error.");     } #endif

#ifdef TPD_PROXIMITY     //obj_ps.self = cm3623_obj;     obj_ps.polling = 0;         //0--interrupt mode;1--polling mode;     obj_ps.sensor_operate = tpd_ps_operate;

    if ((err = hwmsen_attach(ID_PROXIMITY, &obj_ps)))     {         GTP_ERROR("hwmsen attach fail, return:%d.", err);     }

#endif

       tpd_load_status = 1;

    return 0; }

#ifdef CONFIG_OF_TOUCH static irqreturn_t tpd_eint_interrupt_handler(unsigned irq, struct irq_desc *desc) {  TPD_DEBUG_PRINT_INT;     tpd_flag = 1;  /* enter EINT handler disable INT, make sure INT is disable when handle touch event including top/bottom half */  /* use _nosync to avoid deadlock */  //disable_irq_nosync(touch_irq);  //irq_flag--;  //GTP_INFO("disable irq_flag=%d",irq_flag);  wake_up_interruptible(&waiter);     return IRQ_HANDLED; } #else static void tpd_eint_interrupt_handler(void) {  TPD_DEBUG_PRINT_INT;

 tpd_flag = 1;

 wake_up_interruptible(&waiter); } #endif /* static void tpd_eint_interrupt_handler(void) {     TPD_DEBUG_PRINT_INT;         tpd_flag = 1;         wake_up_interruptible(&waiter); }*/

static int tpd_i2c_remove(struct i2c_client *client) { #if GTP_CREATE_WR_NODE     uninit_wr_node(); #endif

#if GTP_ESD_PROTECT     destroy_workqueue(gtp_esd_check_workqueue); #endif     sysfs_remove_group(&mx_tsp->kobj,&gesture_attribute_group);     root_device_unregister(mx_tsp);

    return 0; } #if (GTP_ESD_PROTECT || GTP_COMPATIBLE_MODE) static void force_reset_guitar(void) {     s32 i = 0;     s32 ret = 0;

    GTP_INFO("force_reset_guitar");         //mt65xx_eint_mask(CUST_EINT_TOUCH_PANEL_NUM);  gtp_irq_disable();        GTP_GPIO_OUTPUT(GTP_RST_PORT, 0);       GTP_GPIO_OUTPUT(GTP_INT_PORT, 0); #ifdef MT6573     //Power off TP     mt_set_gpio_mode(GPIO_CTP_EN_PIN, GPIO_CTP_EN_PIN_M_GPIO);     mt_set_gpio_dir(GPIO_CTP_EN_PIN, GPIO_DIR_OUT);     mt_set_gpio_out(GPIO_CTP_EN_PIN, GPIO_OUT_ZERO);      msleep(30);     //Power on TP     mt_set_gpio_out(GPIO_CTP_EN_PIN, GPIO_OUT_ONE);     msleep(30); #else           // ( defined(MT6575) || defined(MT6577) || defined(MT6589) )     // Power off TP     #ifdef TPD_POWER_SOURCE_CUSTOM         hwPowerDown(TPD_POWER_SOURCE_CUSTOM, "TP");     #else         hwPowerDown(MT65XX_POWER_LDO_VGP2, "TP");     #endif         msleep(30);

    // Power on TP     #ifdef TPD_POWER_SOURCE_CUSTOM         hwPowerOn(TPD_POWER_SOURCE_CUSTOM, VOL_2800, "TP");     #else         hwPowerOn(MT65XX_POWER_LDO_VGP2, VOL_2800, "TP");     #endif         msleep(30);

#endif

    for (i = 0; i < 5; i++)     {     #if GTP_COMPATIBLE_MODE         if (CHIP_TYPE_GT9F == gtp_chip_type)         {             ret = gup_fw_download_proc(NULL, GTP_FL_ESD_RECOVERY);             if(FAIL == ret)             {                 GTP_ERROR("[force_reset_guitar]Check & repair fw failed.");                 continue;             }             //startup fw             ret = gtp_fw_startup(i2c_client_point);             if(FAIL == ret)             {                 GTP_ERROR("[force_reset_guitar]Startup fw failed.");                 continue;             }             break;         }         else     #endif         {             //Reset Guitar             gtp_reset_guitar(i2c_client_point, 20);             msleep(50);             //Send config             ret = gtp_send_cfg(i2c_client_point);                 if (ret < 0)             {                 continue;             }         }         break;     }     //mt65xx_eint_unmask(CUST_EINT_TOUCH_PANEL_NUM);     gtp_irq_enable();         if (i >= 5)     {         GTP_ERROR("Failed to reset guitar.");         return;     }     GTP_INFO("Esd recovery successful");     return; } #endif

#if GTP_ESD_PROTECT static s32 gtp_init_ext_watchdog(struct i2c_client *client) {     u8 opr_buffer[2] = {0xAA};     GTP_DEBUG("Init external watchdog.");     return i2c_write_bytes(client, 0x8041, opr_buffer, 1); }

void gtp_esd_switch(struct i2c_client *client, s32 on) {     spin_lock(&esd_lock);         if (SWITCH_ON == on)     // switch on esd     {         if (!esd_running)         {             esd_running = 1;             spin_unlock(&esd_lock);             GTP_INFO("Esd started");             queue_delayed_work(gtp_esd_check_workqueue, &gtp_esd_check_work, clk_tick_cnt);         }         else         {             spin_unlock(&esd_lock);         }     }     else    // switch off esd     {         if (esd_running)         {             esd_running = 0;             spin_unlock(&esd_lock);             GTP_INFO("Esd cancelled");             cancel_delayed_work_sync(&gtp_esd_check_work);         }         else         {             spin_unlock(&esd_lock);         }     } }

static void gtp_esd_check_func(struct work_struct *work) {     s32 i = 0;     s32 ret = -1;     u8 esd_buf[3] = {0x00};     if ((tpd_halt) || (gtp_loading_fw))     {         GTP_INFO("Esd suspended or IC update firmware!");         return;     }     for (i = 0; i < 3; i++)     {         ret = i2c_read_bytes_non_dma(i2c_client_point, 0x8040, esd_buf, 2);                 GTP_DEBUG("[Esd]0x8040 = 0x%02X, 0x8041 = 0x%02X", esd_buf[0], esd_buf[1]);         if (ret < 0)         {             // IIC communication problem             continue;         }         else         {             if ((esd_buf[0] == 0xAA) || (esd_buf[1] != 0xAA))             {                 u8 chk_buf[2] = {0x00};                 i2c_read_bytes_non_dma(i2c_client_point, 0x8040, chk_buf, 2);                                 GTP_DEBUG("[Check]0x8040 = 0x%02X, 0x8041 = 0x%02X", chk_buf[0], chk_buf[1]);                                 if ( (chk_buf[0] == 0xAA) || (chk_buf[1] != 0xAA) )                 {                     i = 3;          // jump to reset guitar                     break;                 }                 else                 {                     continue;                 }             }             else             {                 // IC works normally, Write 0x8040 0xAA, feed the watchdog                 esd_buf[0] = 0xAA;                 i2c_write_bytes_non_dma(i2c_client_point, 0x8040, esd_buf, 1);                                 break;             }         }     }

    if (i >= 3)     {       #if GTP_COMPATIBLE_MODE         if ((CHIP_TYPE_GT9F == gtp_chip_type) && (1 == rqst_processing))         {             GTP_INFO("Request Processing, no reset guitar.");         }         else     #endif         {             GTP_INFO("IC works abnormally! Process reset guitar.");             esd_buf[0] = 0x01;             esd_buf[1] = 0x01;             esd_buf[2] = 0x01;             i2c_write_bytes(i2c_client_point, 0x4226, esd_buf, 3);              msleep(50);             force_reset_guitar();         }     }

    if (!tpd_halt)     {         queue_delayed_work(gtp_esd_check_workqueue, &gtp_esd_check_work, clk_tick_cnt);     }     else     {         GTP_INFO("Esd suspended!");     }

    return; } #endif

static void tpd_down(s32 x, s32 y, s32 size, s32 id) {     if ((!size) && (!id))     {         input_report_abs(tpd->dev, ABS_MT_PRESSURE, 100);         input_report_abs(tpd->dev, ABS_MT_TOUCH_MAJOR, 100);     }     else     {         input_report_abs(tpd->dev, ABS_MT_PRESSURE, size);         input_report_abs(tpd->dev, ABS_MT_TOUCH_MAJOR, size);         /* track id Start 0 */         input_report_abs(tpd->dev, ABS_MT_TRACKING_ID, id);     }

    input_report_key(tpd->dev, BTN_TOUCH, 1);     input_report_abs(tpd->dev, ABS_MT_POSITION_X, x);     input_report_abs(tpd->dev, ABS_MT_POSITION_Y, y);     input_mt_sync(tpd->dev);     TPD_EM_PRINT(x, y, x, y, id, 1);

#if (defined(MT6575)||defined(MT6577))

    if (FACTORY_BOOT == get_boot_mode() || RECOVERY_BOOT == get_boot_mode())     {         tpd_button(x, y, 1);     }

#endif }

static void tpd_up(s32 x, s32 y, s32 id) {     input_report_key(tpd->dev, BTN_TOUCH, 0);     input_mt_sync(tpd->dev);     TPD_EM_PRINT(x, y, x, y, id, 0);

#if (defined(MT6575) || defined(MT6577))

    if (FACTORY_BOOT == get_boot_mode() || RECOVERY_BOOT == get_boot_mode())     {         tpd_button(x, y, 0);     }

#endif } #if GTP_CHARGER_SWITCH static void gtp_charger_switch(s32 dir_update) {     u32 chr_status = 0;     u8 chr_cmd[3] = {0x80, 0x40};     static u8 chr_pluggedin = 0;     int ret = 0;     #ifdef MT6573     chr_status = *(volatile u32 *)CHR_CON0;     chr_status &= (1 << 13); #else   // ( defined(MT6575) || defined(MT6577) || defined(MT6589) )     chr_status = upmu_is_chr_det(); #endif         if (chr_status)     // charger plugged in     {         if (!chr_pluggedin || dir_update)         {             chr_cmd[2] = 6;             ret = gtp_i2c_write(i2c_client_point, chr_cmd, 3);             if (ret > 0)             {                 GTP_INFO("Update status for Charger Plugin");     if (gtp_send_chr_cfg(i2c_client_point) < 0) {      GTP_ERROR("Send charger config failed.");     } else {      GTP_DEBUG("Send charger config.");     }             }             chr_pluggedin = 1;         }     }     else            // charger plugged out     {         if (chr_pluggedin || dir_update)         {             chr_cmd[2] = 7;             ret = gtp_i2c_write(i2c_client_point, chr_cmd, 3);             if (ret > 0)             {                 GTP_INFO("Update status for Charger Plugout");     if (gtp_send_cfg(i2c_client_point) < 0) {      GTP_ERROR("Send normal config failed.");     } else {      GTP_DEBUG("Send normal config.");     }             }             chr_pluggedin = 0;         }     } } #endif

static int touch_event_handler(void *unused) {     struct sched_param param = { .sched_priority = RTPM_PRIO_TPD };     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 u8 pre_touch = 0;     static u8 pre_key = 0; #if GTP_WITH_PEN     u8 pen_active = 0;     static u8 pre_pen = 0; #endif     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;     #if GTP_COMPATIBLE_MODE     u8  rqst_data[3] = {(u8)(GTP_REG_RQST >> 8), (u8)(GTP_REG_RQST & 0xFF), 0}; #endif

#ifdef TPD_PROXIMITY     s32 err = 0;     hwm_sensor_data sensor_data;     u8 proximity_status; #endif

#if GTP_GESTURE_WAKEUP     u8 doze_buf[3] = {0x81, 0x4B}; #endif

    sched_setscheduler(current, SCHED_RR, &param);     do     {         set_current_state(TASK_INTERRUPTIBLE);                 while (tpd_halt)         {         #if GTP_GESTURE_WAKEUP             if (DOZE_ENABLED == doze_status)             {                 break;             }         #endif             tpd_flag = 0;             msleep(20);         }

        wait_event_interruptible(waiter, tpd_flag != 0);         tpd_flag = 0;         TPD_DEBUG_SET_TIME;         set_current_state(TASK_RUNNING);

    #if GTP_CHARGER_SWITCH         gtp_charger_switch(0);     #endif

    #if GTP_GESTURE_WAKEUP  if(p_gesture_control == 0)  {         if (DOZE_ENABLED == doze_status)         {             ret = gtp_i2c_read(i2c_client_point, doze_buf, 3);             GTP_DEBUG("0x814B = 0x%02X", doze_buf[2]);             if (ret > 0)             {                              // if ((doze_buf[2] == 'a') || (doze_buf[2] == 'b') || (doze_buf[2] == 'c') ||                //     (doze_buf[2] == 'd') || (doze_buf[2] == 'e') || (doze_buf[2] == 'g') ||                //     (doze_buf[2] == 'h') || (doze_buf[2] == 'm') || (doze_buf[2] == 'o') ||                //     (doze_buf[2] == 'q') || (doze_buf[2] == 's') || (doze_buf[2] == 'v') ||               //      (doze_buf[2] == 'w') || (doze_buf[2] == 'y') || (doze_buf[2] == 'z') ||               //      (doze_buf[2] == 0x5E) /* ^ */|| (doze_buf[2] == 0x3E)/* > */              //       )              /*                 {                     if (doze_buf[2] != 0x5E)                     {                         GTP_INFO("Wakeup by gesture(%c), light up the screen!", doze_buf[2]);                     }                     else                     {                         GTP_INFO("Wakeup by gesture(^), light up the screen!");                     }                     doze_status = DOZE_WAKEUP;                     input_report_key(tpd->dev, KEY_POWER, 1);                     input_sync(tpd->dev);                     input_report_key(tpd->dev, KEY_POWER, 0);                     input_sync(tpd->dev);                     // clear 0x814B                     doze_buf[2] = 0x00;                     gtp_i2c_write(i2c_client_point, doze_buf, 3);                 }                 */                 if ((doze_buf[2] == 'c') || (doze_buf[2] == 'e') || (doze_buf[2] == 'm') ||    (doze_buf[2] == 'o') || (doze_buf[2] == 's') || (doze_buf[2] == 'v') ||                     (doze_buf[2] == 'w') || (doze_buf[2] == 'z')                     )                 {                  if (((doze_buf[2] == 'v') && ((gesture_three_byte_three & 0x01) == 0x01)) ||         ((doze_buf[2] == 'c') && ((gesture_three_byte_three & 0x02) == 0x02)) ||         ((doze_buf[2] == 'e') && ((gesture_three_byte_three & 0x04) == 0x04)) ||         ((doze_buf[2] == 'w') && ((gesture_three_byte_three & 0x08) == 0x08)) ||         ((doze_buf[2] == 'm') && ((gesture_three_byte_three & 0x10) == 0x10)) ||         ((doze_buf[2] == 's') && ((gesture_three_byte_three & 0x20) == 0x20)) ||         ((doze_buf[2] == 'z') && ((gesture_three_byte_three & 0x40) == 0x40)) ||                           ((doze_buf[2] == 'o') && ((gesture_three_byte_three & 0x80) == 0x80))                     )                  {                      GTP_INFO("Wakeup by gesture(%c), light up the screen!", doze_buf[2]);        doze_status = DOZE_WAKEUP;                         input_report_key(tpd->dev, KEY_GESTURE, 1);                         input_sync(tpd->dev);                         input_report_key(tpd->dev, KEY_GESTURE, 0);                         input_sync(tpd->dev);

                        if(doze_buf[2] == 'v')        {            gesture_data = 0xC6;        }        else if(doze_buf[2] == 'c')        {            gesture_data = 0xC1;        }        else if(doze_buf[2] == 'e')        {            gesture_data = 0xC0;        }        else if(doze_buf[2] == 'w')        {            gesture_data = 0xC2;        }        else if(doze_buf[2] == 'm')        {            gesture_data = 0xC3;        }        else if(doze_buf[2] == 's')        {            gesture_data = 0xC5;        }        else if(doze_buf[2] == 'z')        {            gesture_data = 0xCA;        }        else  //doze_buf[2] == 'o'        {            gesture_data = 0xC4;        }                                // clear 0x814B                         doze_buf[2] = 0x00;                         gtp_i2c_write(i2c_client_point, doze_buf, 3);

       gtp_enter_doze(i2c_client_point);                  }    else    {        // clear 0x814B                         doze_buf[2] = 0x00;                         gtp_i2c_write(i2c_client_point, doze_buf, 3);                         gtp_enter_doze(i2c_client_point);    }                 }                 else if ( (doze_buf[2] == 0xAA) || (doze_buf[2] == 0xBB) ||                     (doze_buf[2] == 0xAB) || (doze_buf[2] == 0xBA) )                 {                     char *direction[4] = {"Right", "Down", "Up", "Left"};                     u8 type = ((doze_buf[2] & 0x0F) - 0x0A) + (((doze_buf[2] >> 4) & 0x0F) - 0x0A) * 2;    if(((type == 0) && ((gesture_three_byte_four & 0x01) == 0x01)) ||     ((type == 1) && ((gesture_three_byte_four & 0x04) == 0x04)) ||     ((type == 2) && ((gesture_three_byte_four & 0x08) == 0x08)) ||     ((type == 3) && ((gesture_three_byte_four & 0x02) ==0x02))    )    {                         GTP_INFO("%s slide to light up the screen!", direction[type]);                         doze_status = DOZE_WAKEUP;                         input_report_key(tpd->dev, KEY_GESTURE, 1);                         input_sync(tpd->dev);                         input_report_key(tpd->dev, KEY_GESTURE, 0);                         input_sync(tpd->dev);                         // clear 0x814B                         doze_buf[2] = 0x00;                         gtp_i2c_write(i2c_client_point, doze_buf, 3);        if(type == 0)        {          gesture_data = 0xB1;        }        else if(type == 1)        {            gesture_data = 0xB3;        }        else if(type == 2)        {            gesture_data = 0xB2;        }        else   //type==3        {            gesture_data = 0xB0;        }

       gtp_enter_doze(i2c_client_point);           }    else    {        // clear 0x814B                         doze_buf[2] = 0x00;                         gtp_i2c_write(i2c_client_point, doze_buf, 3);                         gtp_enter_doze(i2c_client_point);     }                 }                 else if (0xCC == doze_buf[2])                 {                  if((gesture_three_byte_two & 0x01)== 0x01)                  {                          GTP_INFO("Double click to light up the screen!");                          doze_status = DOZE_WAKEUP;                         input_report_key(tpd->dev, KEY_GESTURE, 1);                          input_sync(tpd->dev);                          input_report_key(tpd->dev, KEY_GESTURE, 0);                          input_sync(tpd->dev);                          // clear 0x814B                          doze_buf[2] = 0x00;                          gtp_i2c_write(i2c_client_point, doze_buf, 3);               gesture_data = DOUBLE_TAP;

       gtp_enter_doze(i2c_client_point);                  }    else    {        // clear 0x814B                         doze_buf[2] = 0x00;                         gtp_i2c_write(i2c_client_point, doze_buf, 3);                         gtp_enter_doze(i2c_client_point);    }                 }                 else                 {                     // clear 0x814B                     doze_buf[2] = 0x00;                     gtp_i2c_write(i2c_client_point, doze_buf, 3);                     gtp_enter_doze(i2c_client_point);                 }             }             continue;         }  }  else  {   // clear 0x814B              doze_buf[2] = 0x00;              gtp_i2c_write(i2c_client_point, doze_buf, 3);              gtp_enter_doze(i2c_client_point);  }     #endif         ret = gtp_i2c_read(i2c_client_point, point_data, 12);         if (ret < 0)         {             GTP_ERROR("I2C transfer error. errno:%d\n ", ret);             continue;         }         finger = point_data[GTP_ADDR_LENGTH];             #if GTP_COMPATIBLE_MODE         if ((finger == 0x00) && (CHIP_TYPE_GT9F == gtp_chip_type))         {             ret = gtp_i2c_read(i2c_client_point, rqst_data, 3);

            if(ret < 0)             {                 GTP_ERROR("I2C transfer error. errno:%d\n ", ret);                 continue;             }             switch (rqst_data[2])             {                 case GTP_RQST_BAK_REF:                     GTP_INFO("Request Ref.");                     rqst_processing = 1;                     ret = gtp_bak_ref_proc(i2c_client_point, GTP_BAK_REF_SEND);                     if(SUCCESS == ret)                     {                         GTP_INFO("Send ref success.");                         rqst_data[2] = GTP_RQST_RESPONDED;                         gtp_i2c_write(i2c_client_point, rqst_data, 3);                         rqst_processing = 0;                     }                     goto exit_work_func;                                     case GTP_RQST_CONFIG:                     GTP_INFO("Request Config.");                     ret = gtp_send_cfg(i2c_client_point);                     if (ret < 0)                     {                         GTP_ERROR("Send config error.");                     }                     else                     {                         GTP_INFO("Send config success.");                         rqst_data[2] = GTP_RQST_RESPONDED;                         gtp_i2c_write(i2c_client_point, rqst_data, 3);                     }                     goto exit_work_func;                                     case GTP_RQST_MAIN_CLOCK:                     GTP_INFO("Request main clock.");                     rqst_processing = 1;                     ret = gtp_main_clk_proc(i2c_client_point);                     if(SUCCESS == ret)                     {                         GTP_INFO("Send main clk success.");                                                 rqst_data[2] = GTP_RQST_RESPONDED;                         gtp_i2c_write(i2c_client_point, rqst_data, 3);                         rqst_processing = 0;                     }                     goto exit_work_func;                                     case GTP_RQST_RESET:                     GTP_INFO("Request Reset.");                     gtp_recovery_reset(i2c_client_point);                     goto exit_work_func;                                     default:                     GTP_INFO("Undefined request code: 0x%02X", rqst_data[2]);                     rqst_data[2] = GTP_RQST_RESPONDED;                     gtp_i2c_write(i2c_client_point, rqst_data, 3);                     break;             }         }     #endif             if (finger == 0x00)         {             continue;         }                 if ((finger & 0x80) == 0)         {             goto exit_work_func;         }             #ifdef TPD_PROXIMITY         if (tpd_proximity_flag == 1)         {             proximity_status = point_data[GTP_ADDR_LENGTH];             GTP_DEBUG("REG INDEX[0x814E]:0x%02X\n", proximity_status);

            if (proximity_status & 0x60)                //proximity or large touch detect,enable hwm_sensor.             {                 tpd_proximity_detect = 0;                 //sensor_data.values[0] = 0;             }             else             {                 tpd_proximity_detect = 1;                 //sensor_data.values[0] = 1;             }

            //get raw data             GTP_DEBUG(" ps change\n");             GTP_DEBUG("PROXIMITY STATUS:0x%02X\n", tpd_proximity_detect);             //map and store data to hwm_sensor_data             sensor_data.values[0] = tpd_get_ps_value();             sensor_data.value_divide = 1;             sensor_data.status = SENSOR_STATUS_ACCURACY_MEDIUM;             //report to the up-layer             ret = hwmsen_get_interrupt_data(ID_PROXIMITY, &sensor_data);

            if (ret)             {                 GTP_ERROR("Call hwmsen_get_interrupt_data fail = %d\n", err);             }         }

    #endif

        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(i2c_client_point, buf, 2 + 8 * (touch_num - 1));             memcpy(&point_data[12], &buf[2], 8 * (touch_num - 1));         }

    #if (GTP_HAVE_TOUCH_KEY || GTP_PEN_HAVE_BUTTON)         key_value = point_data[3 + 8 * touch_num];

        if (key_value || pre_key)         {         #if GTP_PEN_HAVE_BUTTON             if (key_value == 0x40)             {                 GTP_DEBUG("BTN_STYLUS & BTN_STYLUS2 Down.");                 input_report_key(pen_dev, BTN_STYLUS, 1);                 input_report_key(pen_dev, BTN_STYLUS2, 1);                 pen_active = 1;             }             else if (key_value == 0x10)             {                 GTP_DEBUG("BTN_STYLUS Down, BTN_STYLUS2 Up.");                 input_report_key(pen_dev, BTN_STYLUS, 1);                 input_report_key(pen_dev, BTN_STYLUS2, 0);                 pen_active = 1;             }             else if (key_value == 0x20)             {                 GTP_DEBUG("BTN_STYLUS Up, BTN_STYLUS2 Down.");                 input_report_key(pen_dev, BTN_STYLUS, 0);                 input_report_key(pen_dev, BTN_STYLUS2, 1);                 pen_active = 1;             }             else             {                 GTP_DEBUG("BTN_STYLUS & BTN_STYLUS2 Up.");                 input_report_key(pen_dev, BTN_STYLUS, 0);                 input_report_key(pen_dev, BTN_STYLUS2, 0);                 if ( (pre_key == 0x40) || (pre_key == 0x20) ||                      (pre_key == 0x10)                    )                 {                     pen_active = 1;                 }             }             if (pen_active)             {                 touch_num = 0;      // shield pen point                 //pre_touch = 0;    // clear last pen status             }         #endif         #if GTP_HAVE_TOUCH_KEY             if (!pre_touch)             {                 for (i = 0; i < GTP_MAX_KEY_NUM; i++)                 {                     input_report_key(tpd->dev, touch_key_array[i], key_value & (0x01 << i));                 }                 touch_num = 0;  // shiled fingers             }         #endif         }     #endif         pre_key = key_value;

        GTP_DEBUG("pre_touch:%02x, finger:%02x.", pre_touch, finger);                 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;

                input_x = TPD_WARP_X(abs_x_max, input_x);                 input_y = TPD_WARP_Y(abs_y_max, input_y);

            #if GTP_WITH_PEN                 id = coor_data[0];                 if ((id & 0x80))      // pen/stylus is activated                 {                     GTP_DEBUG("Pen touch DOWN!");                     pre_pen = 1;                     //id &= 0x7F;                     id = 0;                     GTP_DEBUG("(%d)(%d, %d)[%d]", id, input_x, input_y, input_w);                     gtp_pen_down(input_x, input_y, input_w, id);                     pen_active = 1;                 }                 else             #endif                 {                     GTP_DEBUG(" (%d)(%d, %d)[%d]", id, input_x, input_y, input_w);                     tpd_down(input_x, input_y, input_w, id);                 }             }         }         else         {             if (pre_touch)             {             #if GTP_WITH_PEN                 if (pre_pen)                 {                       GTP_DEBUG("Pen touch UP!");                     gtp_pen_up();                     pre_pen = 0;                     pen_active = 1;                 }                 else             #endif                 {                     GTP_DEBUG("Touch Release!");                     tpd_up(0, 0, 0);                 }             }         }         pre_touch = touch_num;       #if GTP_WITH_PEN         if (pen_active)         {             pen_active = 0;             input_sync(pen_dev);         }         else     #endif         {             input_sync(tpd->dev);         }

exit_work_func:

        if (!gtp_rawdiff_mode)         {             ret = gtp_i2c_write(i2c_client_point, end_cmd, 3);

            if (ret < 0)             {                 GTP_INFO("I2C write end_cmd  error!");             }         }

    } while (!kthread_should_stop());

    return 0; }

static int tpd_local_init(void) {   #ifdef TPD_POWER_SOURCE_CUSTOM #ifdef CONFIG_OF_TOUCH #ifdef CONFIG_ARCH_MT6580  tpd->reg=regulator_get(tpd->tpd_dev,TPD_POWER_SOURCE_CUSTOM); // get pointer to regulator structure  if (IS_ERR(tpd->reg)) {   GTP_ERROR("regulator_get() failed!\n");  } #endif #endif #endif   #if GTP_ESD_PROTECT     clk_tick_cnt = 2 * HZ;   // HZ: clock ticks in 1 second generated by system     GTP_DEBUG("Clock ticks for an esd cycle: %d", clk_tick_cnt);     INIT_DELAYED_WORK(&gtp_esd_check_work, gtp_esd_check_func);     gtp_esd_check_workqueue = create_workqueue("gtp_esd_check");     spin_lock_init(&esd_lock);          // 2.6.39 & later     // esd_lock = SPIN_LOCK_UNLOCKED;   // 2.6.39 & before #endif

#if GTP_SUPPORT_I2C_DMA     tpd->dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);     gpDMABuf_va = (u8 *)dma_alloc_coherent(&tpd->dev->dev, GTP_DMA_MAX_TRANSACTION_LENGTH, &gpDMABuf_pa, GFP_KERNEL);     if(!gpDMABuf_va){         GTP_INFO("[Error] Allocate DMA I2C Buffer failed!\n");     }     memset(gpDMABuf_va, 0, GTP_DMA_MAX_TRANSACTION_LENGTH); #endif     if (i2c_add_driver(&tpd_i2c_driver) != 0)     {         GTP_INFO("unable to add i2c driver.\n");         return -1;     }

    if (tpd_load_status == 0) //if(tpd_load_status == 0) // disable auto load touch driver for linux3.0 porting     {         GTP_INFO("add error touch panel driver.\n");         i2c_del_driver(&tpd_i2c_driver);         return -1;     }

#ifdef TPD_HAVE_BUTTON     tpd_button_setting(TPD_KEY_COUNT, tpd_keys_local, tpd_keys_dim_local);// initialize tpd button data #endif

#if (defined(TPD_WARP_START) && defined(TPD_WARP_END))     TPD_DO_WARP = 1;     memcpy(tpd_wb_start, tpd_wb_start_local, TPD_WARP_CNT * 4);     memcpy(tpd_wb_end, tpd_wb_start_local, TPD_WARP_CNT * 4); #endif

#if (defined(TPD_HAVE_CALIBRATION) && !defined(TPD_CUSTOM_CALIBRATION))     memcpy(tpd_calmat, tpd_def_calmat_local, 8 * 4);     memcpy(tpd_def_calmat, tpd_def_calmat_local, 8 * 4); #endif

    // set vendor string     tpd->dev->id.vendor = 0x00;     tpd->dev->id.product = tpd_info.pid;     tpd->dev->id.version = tpd_info.vid;

    GTP_INFO("end %s, %d\n", __FUNCTION__, __LINE__);     tpd_type_cap = 1;

    return 0; }

static s8 gtp_enter_doze(struct i2c_client *client) {     s8 ret = -1;     s8 retry = 0;     u8 i2c_control_buf[3] = {(u8)(GTP_REG_SLEEP >> 8), (u8)GTP_REG_SLEEP, 8};

    GTP_DEBUG_FUNC();

    GTP_DEBUG("Entering gesture mode...");     while(retry++ < 5)     {         i2c_control_buf[0] = 0x80;         i2c_control_buf[1] = 0x46;         ret = gtp_i2c_write(client, i2c_control_buf, 3);         if (ret < 0)         {             GTP_DEBUG("Failed to set gesture flag into 0x8046, %d", retry);             continue;         }         i2c_control_buf[0] = 0x80;         i2c_control_buf[1] = 0x40;         ret = gtp_i2c_write(client, i2c_control_buf, 3);         if (ret > 0)         {             doze_status = DOZE_ENABLED;             GTP_INFO("Gesture mode enabled.");             return ret;         }         msleep(10);     }     GTP_ERROR("GTP send gesture cmd failed.");     return ret; }

/******************************************************* Function:     Eter sleep function.

Input:     client:i2c_client.

Output:     Executive outcomes.0--success,non-0--fail. *******************************************************/ static s8 gtp_enter_sleep(struct i2c_client *client) { #if GTP_COMPATIBLE_MODE     if (CHIP_TYPE_GT9F == gtp_chip_type)     {         u8 i2c_status_buf[3] = {0x80, 0x44, 0x00};         s32 ret = 0;               ret = gtp_i2c_read(client, i2c_status_buf, 3);         if(ret <= 0)         {              GTP_ERROR("[gtp_enter_sleep]Read ref status reg error.");         }                 if (i2c_status_buf[2] & 0x80)         {             //Store bak ref             ret = gtp_bak_ref_proc(client, GTP_BAK_REF_STORE);             if(FAIL == ret)             {                 GTP_ERROR("[gtp_enter_sleep]Store bak ref failed.");             }                }     } #endif #if GTP_POWER_CTRL_SLEEP

    GTP_GPIO_OUTPUT(GTP_RST_PORT, 0);       GTP_GPIO_OUTPUT(GTP_INT_PORT, 0);     msleep(10);

#ifdef MT6573     mt_set_gpio_mode(GPIO_CTP_EN_PIN, GPIO_CTP_EN_PIN_M_GPIO);     mt_set_gpio_dir(GPIO_CTP_EN_PIN, GPIO_DIR_OUT);     mt_set_gpio_out(GPIO_CTP_EN_PIN, GPIO_OUT_ZERO);      msleep(30); #else               // ( defined(MT6575) || defined(MT6577) || defined(MT6589) )

    #ifdef TPD_POWER_SOURCE_1800         hwPowerDown(TPD_POWER_SOURCE_1800, "TP");     #endif         #ifdef TPD_POWER_SOURCE_CUSTOM         hwPowerDown(TPD_POWER_SOURCE_CUSTOM, "TP");     #else         hwPowerDown(MT65XX_POWER_LDO_VGP2, "TP");     #endif #endif        GTP_INFO("GTP enter sleep by poweroff!");     return 0;     #else     {         s8 ret = -1;         s8 retry = 0;         u8 i2c_control_buf[3] = {(u8)(GTP_REG_SLEEP >> 8), (u8)GTP_REG_SLEEP, 5};                         GTP_GPIO_OUTPUT(GTP_INT_PORT, 0);         msleep(5);             while (retry++ < 5)         {             ret = gtp_i2c_write(client, i2c_control_buf, 3);                 if (ret > 0)             {                 GTP_INFO("GTP enter sleep!");                                     return ret;             }                 msleep(10);         }             GTP_ERROR("GTP send sleep cmd failed.");         return ret;     } #endif }

/******************************************************* Function:     Wakeup from sleep mode Function.

Input:     client:i2c_client.

Output:     Executive outcomes.0--success,non-0--fail. *******************************************************/ static s8 gtp_wakeup_sleep(struct i2c_client *client) {     u8 retry = 0;     s8 ret = -1;

    GTP_DEBUG("GTP wakeup begin.");

#if (GTP_POWER_CTRL_SLEEP)  

#if GTP_COMPATIBLE_MODE     if (CHIP_TYPE_GT9F == gtp_chip_type)     {         force_reset_guitar();         GTP_INFO("Esd recovery wakeup.");         return 0;     } #endif

    while (retry++ < 5)     {         ret = tpd_power_on(client);

        if (ret < 0)         {             GTP_ERROR("I2C Power on ERROR!");             continue;         }         GTP_INFO("Ic wakeup by poweron");         return 0;     } #else

#if GTP_COMPATIBLE_MODE     if (CHIP_TYPE_GT9F == gtp_chip_type)     {         u8 opr_buf[2] = {0};                 while (retry++ < 10)         {             GTP_GPIO_OUTPUT(GTP_INT_PORT, 1);             msleep(5);                         ret = gtp_i2c_test(client);                 if (ret >= 0)             {                  // Hold ss51 & dsp                 opr_buf[0] = 0x0C;                 ret = i2c_write_bytes(client, 0x4180, opr_buf, 1);                 if (ret < 0)                 {                     GTP_DEBUG("Hold ss51 & dsp I2C error,retry:%d", retry);                     continue;                 }                                 // Confirm hold                 opr_buf[0] = 0x00;                 ret = i2c_read_bytes(client, 0x4180, opr_buf, 1);                 if (ret < 0)                 {                     GTP_DEBUG("confirm ss51 & dsp hold, I2C error,retry:%d", retry);                     continue;                 }                 if (0x0C != opr_buf[0])                 {                     GTP_DEBUG("ss51 & dsp not hold, val: %d, retry: %d", opr_buf[0], retry);                     continue;                 }                 GTP_DEBUG("ss51 & dsp has been hold");                                 ret = gtp_fw_startup(client);                 if (FAIL == ret)                 {                     GTP_ERROR("[gtp_wakeup_sleep]Startup fw failed.");                     continue;                 }                 GTP_INFO("flashless wakeup sleep success");                 return ret;             }             force_reset_guitar();             retry = 0;             break;         }         if (retry >= 10)         {             GTP_ERROR("wakeup retry timeout, process esd reset");             force_reset_guitar();         }         GTP_ERROR("GTP wakeup sleep failed.");         return ret;     } #endif     while (retry++ < 10)     {     #if GTP_GESTURE_WAKEUP   if((gesture_three_byte_one == 0) || ((gesture_three_byte_two == 0) && (gesture_three_byte_three == 0) && (gesture_three_byte_four == 0)))   {   GTP_GPIO_OUTPUT(GTP_INT_PORT, 1);          msleep(5);   }   else   {              if (DOZE_WAKEUP != doze_status)             {                 GTP_INFO("Powerkey wakeup.");             }             else             {                 GTP_INFO("Gesture wakeup.");             }             doze_status = DOZE_DISABLED;                     gtp_irq_disable();             //mt65xx_eint_mask(CUST_EINT_TOUCH_PANEL_NUM);             gtp_reset_guitar(client, 20);             //mt65xx_eint_unmask(CUST_EINT_TOUCH_PANEL_NUM);             gtp_irq_enable();   }     #else             GTP_GPIO_OUTPUT(GTP_INT_PORT, 1);         msleep(5);     #endif                 ret = gtp_i2c_test(client);

        if (ret >= 0)         {             GTP_INFO("GTP wakeup sleep.");         #if (!GTP_GESTURE_WAKEUP)             {                 gtp_int_sync(25);             #if GTP_ESD_PROTECT                 gtp_init_ext_watchdog(client);             #endif             }         #endif       if((gesture_three_byte_one == 0) || ((gesture_three_byte_two == 0) && (gesture_three_byte_three == 0) && (gesture_three_byte_four == 0)))       {        gtp_int_sync(25);                 #if GTP_ESD_PROTECT                     gtp_init_ext_watchdog(client);                 #endif       }                         return ret;         }         gtp_reset_guitar(client, 20);     } #endif     GTP_ERROR("GTP wakeup sleep failed.");     return ret; }

/* Function to manage low power suspend */ static void tpd_suspend(struct early_suspend *h) {     s32 ret = -1;

    GTP_INFO("System suspend.");

#ifdef TPD_PROXIMITY

    if (tpd_proximity_flag == 1)     {         return ;     }

#endif

    tpd_halt = 1; #if GTP_ESD_PROTECT     gtp_esd_switch(i2c_client_point, SWITCH_OFF); #endif     #if GTP_GESTURE_WAKEUP     if((gesture_three_byte_one == 0) || ((gesture_three_byte_two == 0) && (gesture_three_byte_three == 0) && (gesture_three_byte_four == 0)))     {         gtp_irq_disable();            ret = gtp_enter_sleep(i2c_client_point);     }     else    {  ret = gtp_enter_doze(i2c_client_point);     } #else        //mt65xx_eint_mask(CUST_EINT_TOUCH_PANEL_NUM);     gtp_irq_disable();         ret = gtp_enter_sleep(i2c_client_point); #endif     if (ret < 0)     {         GTP_ERROR("GTP early suspend failed.");     }     // to avoid waking up while not sleeping, delay 48 + 10ms to ensure reliability     msleep(58); }

/* Function to manage power-on resume */ static void tpd_resume(struct early_suspend *h) {     s32 ret = -1;

    GTP_INFO("System resume.");     #ifdef TPD_PROXIMITY

    if (tpd_proximity_flag == 1)     {         return ;     }

#endif     ret = gtp_wakeup_sleep(i2c_client_point);

    if (ret < 0)     {         GTP_ERROR("GTP later resume failed.");     }     #if GTP_COMPATIBLE_MODE     if (CHIP_TYPE_GT9F == gtp_chip_type)     {         // do nothing     }     else #endif     {         gtp_send_cfg(i2c_client_point);     }     #if GTP_CHARGER_SWITCH     gtp_charger_switch(1);  // force update #endif

    tpd_halt = 0; #if GTP_GESTURE_WAKEUP if((gesture_three_byte_one == 0) || ((gesture_three_byte_two == 0) && (gesture_three_byte_three == 0) && (gesture_three_byte_four == 0))) {  gtp_irq_enable(); } else {     doze_status = DOZE_DISABLED; } #else     //mt65xx_eint_unmask(CUST_EINT_TOUCH_PANEL_NUM);     gtp_irq_enable(); #endif

#if GTP_ESD_PROTECT     gtp_esd_switch(i2c_client_point, SWITCH_ON); #endif

}

static struct tpd_driver_t tpd_device_driver = {     .tpd_device_name = "gt9xx",     .tpd_local_init = tpd_local_init,     .suspend = tpd_suspend,     .resume = tpd_resume, #ifdef TPD_HAVE_BUTTON     .tpd_have_button = 1, #else     .tpd_have_button = 0, #endif };

/* called when loaded into kernel */ static int __init tpd_driver_init(void) {     GTP_INFO("MediaTek gt91xx touch panel driver init\n");

    i2c_register_board_info(I2C_BUS_NUMBER, &i2c_tpd, 1);     if (tpd_driver_add(&tpd_device_driver) < 0)         GTP_INFO("add generic driver failed\n");

    return 0; }

/* should never be called */ static void __exit tpd_driver_exit(void) {     GTP_INFO("MediaTek gt91xx touch panel driver exit\n");     tpd_driver_remove(&tpd_device_driver); #if GTP_COVER_CONTROL     unregister_cover_notifier(&cover_notifier1); #endif #if GTP_P_GESTURE_CONTROL     unregister_gesture_notifier(&gesture_notifier1); #endif }

module_init(tpd_driver_init); module_exit(tpd_driver_exit);

 

 

ltr599.c_new:

#include <linux/interrupt.h> #include <linux/i2c.h> #include <linux/slab.h> #include <linux/irq.h> #include <linux/miscdevice.h> #include <asm/uaccess.h> #include <linux/delay.h> #include <linux/input.h> #include <linux/workqueue.h> #include <linux/kobject.h> #include <linux/earlysuspend.h> #include <linux/platform_device.h> #include <asm/atomic.h>

#include <mach/mt_typedefs.h> #include <mach/mt_gpio.h> #include <mach/mt_pm_ldo.h> #include <linux/hwmsensor.h> #include <linux/hwmsen_dev.h> #include <linux/sensors_io.h> #include <asm/io.h> #include <cust_eint.h> #include <cust_alsps.h> #include <linux/hwmsen_helper.h> #include "ltr559.h"

#include <linux/earlysuspend.h> #include <linux/wakelock.h> #include <linux/sched.h> #include <alsps.h> #include <linux/mutex.h>

#undef CUSTOM_KERNEL_SENSORHUB #ifdef CUSTOM_KERNEL_SENSORHUB #include <SCP_sensorHub.h> #endif

#define POWER_NONE_MACRO MT65XX_POWER_NONE #define GN_MTK_BSP_PS_DYNAMIC_CALI

/******************************************************************************  * configuration *******************************************************************************/ /*----------------------------------------------------------------------------*/

#define LTR559_DEV_NAME   "LTR_559ALS"

/*----------------------------------------------------------------------------*/ #define APS_TAG                  "[ALS/PS] " #define APS_FUN(f)               printk(KERN_ERR APS_TAG"%s\n", __FUNCTION__) #define APS_ERR(fmt, args...)    printk(KERN_ERR  APS_TAG"%s %d : "fmt, __FUNCTION__, __LINE__, ##args)

#define APS_ERR_ST(f)    printk(KERN_ERR  APS_TAG"%s %d : ", __FUNCTION__, __LINE__)

#define APS_LOG(fmt, args...)    printk(KERN_ERR APS_TAG fmt, ##args) #define APS_DBG(fmt, args...)    printk(KERN_ERR APS_TAG fmt, ##args)                 /******************************************************************************  * extern functions *******************************************************************************/

extern void mt_eint_mask(unsigned int eint_num); extern void mt_eint_unmask(unsigned int eint_num); extern void mt_eint_set_hw_debounce(unsigned int eint_num, unsigned int ms); extern void mt_eint_set_polarity(unsigned int eint_num, unsigned int pol); extern unsigned int mt_eint_set_sens(unsigned int eint_num, unsigned int sens); extern void mt_eint_registration(unsigned int eint_num, unsigned int flow, void (EINT_FUNC_PTR)(void), unsigned int is_auto_umask); extern void mt_eint_print_status(void);

extern int gesture_notifier_call_chain(unsigned long val, void *v);  //add by chen gesture /*----------------------------------------------------------------------------*/

static struct i2c_client *ltr559_i2c_client = NULL;

/*----------------------------------------------------------------------------*/ static const struct i2c_device_id ltr559_i2c_id[] = {{LTR559_DEV_NAME,0},{}}; /*the adapter id & i2c address will be available in customization*/ static struct i2c_board_info __initdata i2c_ltr559={ I2C_BOARD_INFO("LTR_559ALS", 0x23)};

//static unsigned short ltr559_force[] = {0x00, 0x46, I2C_CLIENT_END, I2C_CLIENT_END}; //static const unsigned short *const ltr559_forces[] = { ltr559_force, NULL }; //static struct i2c_client_address_data ltr559_addr_data = { .forces = ltr559_forces,}; /*----------------------------------------------------------------------------*/ static int ltr559_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id); static int ltr559_i2c_remove(struct i2c_client *client); static int ltr559_i2c_detect(struct i2c_client *client, int kind, struct i2c_board_info *info); /*----------------------------------------------------------------------------*/ static int ltr559_i2c_suspend(struct i2c_client *client, pm_message_t msg); static int ltr559_i2c_resume(struct i2c_client *client); static int ltr559_init_device(void);

static int ltr559_ps_enable(int gainrange); static int dynamic_calibrate=0;

static int ps_trigger_high = 800;  static int ps_trigger_low = 760;

static int ps_gainrange; static int als_gainrange;

static int final_prox_val , prox_val; static int final_lux_val;

/*----------------------------------------------------------------------------*/ static DEFINE_MUTEX(read_lock);

/*----------------------------------------------------------------------------*/ static int ltr559_als_read(int gainrange); static int ltr559_ps_read(void);

/*----------------------------------------------------------------------------*/

typedef enum {     CMC_BIT_ALS    = 1,     CMC_BIT_PS     = 2, } CMC_BIT;

/*----------------------------------------------------------------------------*/ struct ltr559_i2c_addr {    /*define a series of i2c slave address*/     u8  write_addr;      u8  ps_thd;     /*PS INT threshold*/ };

/*----------------------------------------------------------------------------*/

struct ltr559_priv {     struct alsps_hw  *hw;     struct i2c_client *client;     struct work_struct  eint_work;     struct mutex lock;  /*i2c address group*/     struct ltr559_i2c_addr  addr;

     /*misc*/     u16      als_modulus;     atomic_t    i2c_retry;     atomic_t    als_debounce;   /*debounce time after enabling als*/     atomic_t    als_deb_on;     /*indicates if the debounce is on*/     atomic_t    als_deb_end;    /*the jiffies representing the end of debounce*/     atomic_t    ps_mask;        /*mask ps: always return far away*/     atomic_t    ps_debounce;    /*debounce time after enabling ps*/     atomic_t    ps_deb_on;      /*indicates if the debounce is on*/     atomic_t    ps_deb_end;     /*the jiffies representing the end of debounce*/     atomic_t    ps_suspend;     atomic_t    als_suspend;

    /*data*/     u16         als;     u16          ps;     u8          _align;     u16         als_level_num;     u16         als_value_num;     u32         als_level[C_CUST_ALS_LEVEL-1];     u32         als_value[C_CUST_ALS_LEVEL];

    atomic_t    als_cmd_val;    /*the cmd value can't be read, stored in ram*/     atomic_t    ps_cmd_val;     /*the cmd value can't be read, stored in ram*/     atomic_t    ps_thd_val;     /*the cmd value can't be read, stored in ram*/  atomic_t    ps_thd_val_high;     /*the cmd value can't be read, stored in ram*/  atomic_t    ps_thd_val_low;     /*the cmd value can't be read, stored in ram*/     ulong       enable;         /*enable mask*/     ulong       pending_intr;   /*pending interrupt*/

    /*early suspend*/ #if defined(CONFIG_HAS_EARLYSUSPEND)     struct early_suspend    early_drv; #endif     };

 struct PS_CALI_DATA_STRUCT {     int close;     int far_away;     int valid; } ;

static struct PS_CALI_DATA_STRUCT ps_cali={0,0,0}; static int intr_flag_value = 0;

static struct ltr559_priv *ltr559_obj = NULL; static struct platform_driver ltr559_alsps_driver;

/*----------------------------------------------------------------------------*/ static struct i2c_driver ltr559_i2c_driver = {   .probe      = ltr559_i2c_probe,  .remove     = ltr559_i2c_remove,  .detect     = ltr559_i2c_detect,  .suspend    = ltr559_i2c_suspend,  .resume     = ltr559_i2c_resume,  .id_table   = ltr559_i2c_id,  //.address_data = &ltr559_addr_data,  .driver = {   //.owner          = THIS_MODULE,   .name           = LTR559_DEV_NAME,  }, };

/*  * #########  * ## I2C ##  * #########  */

// I2C Read static int ltr559_i2c_read_reg(u8 regnum) {     u8 buffer[1],reg_value[1];  int res = 0;  mutex_lock(&read_lock);    buffer[0]= regnum;  res = i2c_master_send(ltr559_obj->client, buffer, 0x1);  if(res <= 0) {         APS_ERR("read reg send res = %d\n",res);   return res;  }  res = i2c_master_recv(ltr559_obj->client, reg_value, 0x1);  if(res <= 0)  {   APS_ERR("read reg recv res = %d\n",res);   return res;  }  mutex_unlock(&read_lock);  return reg_value[0]; }

// I2C Write static int ltr559_i2c_write_reg(u8 regnum, u8 value) {  u8 databuf[2];     int res = 0;     databuf[0] = regnum;    databuf[1] = value;  res = i2c_master_send(ltr559_obj->client, databuf, 0x2);

 if (res < 0)   {    APS_ERR("wirte reg send res = %d\n",res);       return res;   }     else   return 0; }

/*----------------------------------------------------------------------------*/ #ifdef GN_MTK_BSP_PS_DYNAMIC_CALI static ssize_t ltr559_dynamic_calibrate(void)    {                      int ret=0;  int i=0;  int data;  int data_total=0;  ssize_t len = 0;  int noise = 0;  int count = 5;  int max = 0;  struct ltr559_priv *obj = ltr559_obj;  if(!ltr559_obj)  {    APS_ERR("ltr559_obj is null!!\n");   //len = sprintf(buf, "ltr559_obj is null\n");   return -1;  }

 // wait for register to be stable  msleep(15);

 for (i = 0; i < count; i++) {   // wait for ps value be stable      msleep(15);      data=ltr559_ps_read();   if (data < 0) {    i--;    continue;   }        if(data & 0x8000){    noise = 0;    break;   }else{    noise=data;   }       data_total+=data;

  if (max++ > 100) {    //len = sprintf(buf,"adjust fail\n");    return len;   }  }

   noise=data_total/count;

 dynamic_calibrate = noise;  if(noise < 100){

   atomic_set(&obj->ps_thd_val_high,  noise+80);//wangxiqiang    atomic_set(&obj->ps_thd_val_low, noise+60);  }else if(noise < 200){    atomic_set(&obj->ps_thd_val_high,  noise+100);    atomic_set(&obj->ps_thd_val_low, noise+80);  }else if(noise < 300){    atomic_set(&obj->ps_thd_val_high,  noise+100);    atomic_set(&obj->ps_thd_val_low, noise+80);  }else if(noise < 400){    atomic_set(&obj->ps_thd_val_high,  noise+100);    atomic_set(&obj->ps_thd_val_low, noise+80);  }else if(noise < 600){    atomic_set(&obj->ps_thd_val_high,  noise+180);    atomic_set(&obj->ps_thd_val_low, noise+90);  }else if(noise < 1000){   atomic_set(&obj->ps_thd_val_high,  noise+300);   atomic_set(&obj->ps_thd_val_low, noise+180);   }else if(noise < 1250){    atomic_set(&obj->ps_thd_val_high,  noise+400);    atomic_set(&obj->ps_thd_val_low, noise+300);  }  else{    atomic_set(&obj->ps_thd_val_high,  1300);    atomic_set(&obj->ps_thd_val_low, 1000);    //isadjust = 0;   printk(KERN_ERR "ltr558 the proximity sensor structure is error\n");  }    //  int ps_thd_val_low, ps_thd_val_high ;    ps_thd_val_low = atomic_read(&obj->ps_thd_val_low);  ps_thd_val_high = atomic_read(&obj->ps_thd_val_high);

 return 0; } #endif

/*----------------------------------------------------------------------------*/ static ssize_t ltr559_show_als(struct device_driver *ddri, char *buf) {  int res;  u8 dat = 0;    if(!ltr559_obj)  {   APS_ERR("ltr559_obj is null!!\n");   return 0;  }  res = ltr559_als_read(als_gainrange);     return snprintf(buf, PAGE_SIZE, "0x%04X\n", res);      } /*----------------------------------------------------------------------------*/ static ssize_t ltr559_show_ps(struct device_driver *ddri, char *buf) {  int  res;  if(!ltr559_obj)  {   APS_ERR("ltr559_obj is null!!\n");   return 0;  }  res = ltr559_ps_read();     return snprintf(buf, PAGE_SIZE, "0x%04X\n", res);     } /*----------------------------------------------------------------------------*/

/*----------------------------------------------------------------------------*/ static ssize_t ltr559_show_status(struct device_driver *ddri, char *buf) {  ssize_t len = 0;    if(!ltr559_obj)  {   APS_ERR("ltr559_obj is null!!\n");   return 0;  }    if(ltr559_obj->hw)  {     len += snprintf(buf+len, PAGE_SIZE-len, "CUST: %d, (%d %d)\n",    ltr559_obj->hw->i2c_num, ltr559_obj->hw->power_id, ltr559_obj->hw->power_vol);     }  else  {   len += snprintf(buf+len, PAGE_SIZE-len, "CUST: NULL\n");  }

 len += snprintf(buf+len, PAGE_SIZE-len, "MISC: %d %d\n", atomic_read(&ltr559_obj->als_suspend), atomic_read(&ltr559_obj->ps_suspend));

 return len; }

/*----------------------------------------------------------------------------*/ static ssize_t ltr559_store_status(struct device_driver *ddri, char *buf, size_t count) {  int status1,ret;  if(!ltr559_obj)  {   APS_ERR("ltr559_obj is null!!\n");   return 0;  }    if(1 == sscanf(buf, "%d ", &status1))  {      ret=ltr559_ps_enable(ps_gainrange);   APS_DBG("iret= %d, ps_gainrange = %d\n", ret, ps_gainrange);  }  else  {   APS_DBG("invalid content: '%s', length = %ld\n", buf, count);  }  return count;    }

/*----------------------------------------------------------------------------*/ static ssize_t ltr559_show_reg(struct device_driver *ddri, char *buf, size_t count) {  int i,len=0;  int reg[]={0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,   0x8d,0x8e,0x8f,0x90,0x91,0x92,0x93,0x94,0x95,0x97,0x98,0x99,0x9a,0x9e};  for(i=0;i<27;i++)   {   len += snprintf(buf+len, PAGE_SIZE-len, "reg:0x%04X value: 0x%04X\n", reg[i],ltr559_i2c_read_reg(reg[i])); 

     }  return len; } /*----------------------------------------------------------------------------*/ static ssize_t ltr559_store_reg(struct device_driver *ddri, char *buf, size_t count) {  int ret,value;  u32 reg;  if(!ltr559_obj)  {   APS_ERR("ltr559_obj is null!!\n");   return 0;  }    if(2 == sscanf(buf, "%x %x ", &reg,&value))  {   APS_DBG("before write reg: %x, reg_value = %x  write value=%x\n", reg,ltr559_i2c_read_reg(reg),value);      ret=ltr559_i2c_write_reg(reg,value);   APS_DBG("after write reg: %x, reg_value = %x\n", reg,ltr559_i2c_read_reg(reg));  }  else  {   APS_DBG("invalid content: '%s', length = %ld\n", buf, count);  }  return count;    }

/*----------------------------------------------------------------------------*/ static DRIVER_ATTR(als,     S_IWUSR | S_IRUGO, ltr559_show_als,   NULL); static DRIVER_ATTR(ps,      S_IWUSR | S_IRUGO, ltr559_show_ps,    NULL); //static DRIVER_ATTR(config,  S_IWUSR | S_IRUGO, ltr559_show_config,ltr559_store_config); //static DRIVER_ATTR(alslv,   S_IWUSR | S_IRUGO, ltr559_show_alslv, ltr559_store_alslv); //static DRIVER_ATTR(alsval,  S_IWUSR | S_IRUGO, ltr559_show_alsval,ltr559_store_alsval); //static DRIVER_ATTR(trace,   S_IWUSR | S_IRUGO,ltr559_show_trace, ltr559_store_trace); static DRIVER_ATTR(status,  S_IWUSR | S_IRUGO, ltr559_show_status,  ltr559_store_status); static DRIVER_ATTR(reg,     S_IWUSR | S_IRUGO, ltr559_show_reg,   ltr559_store_reg); //static DRIVER_ATTR(i2c,     S_IWUSR | S_IRUGO, ltr559_show_i2c,   ltr559_store_i2c); /*----------------------------------------------------------------------------*/ static struct driver_attribute *ltr559_attr_list[] = {     &driver_attr_als,     &driver_attr_ps,       // &driver_attr_trace,        /*trace log*/    // &driver_attr_config,    // &driver_attr_alslv,    //&driver_attr_alsval,     &driver_attr_status,    //&driver_attr_i2c,     &driver_attr_reg, }; /*----------------------------------------------------------------------------*/ static int ltr559_create_attr(struct driver_attribute *driver) {  int idx, err = 0;  int num = (int)(sizeof(ltr559_attr_list)/sizeof(ltr559_attr_list[0]));

 if (driver == NULL)  {   return -EINVAL;  }

 for(idx = 0; idx < num; idx++)  {   if(err = driver_create_file(driver, ltr559_attr_list[idx]))   {               APS_ERR("driver_create_file (%s) = %d\n", ltr559_attr_list[idx]->attr.name, err);    break;   }  }     return err; } /*----------------------------------------------------------------------------*/  static int ltr559_delete_attr(struct device_driver *driver)  {  int idx ,err = 0;  int num = (int)(sizeof(ltr559_attr_list)/sizeof(ltr559_attr_list[0]));

 if (!driver)  return -EINVAL;

 for (idx = 0; idx < num; idx++)  {   driver_remove_file(driver, ltr559_attr_list[idx]);  }    return err; }

/*----------------------------------------------------------------------------*/

/*  * ###############  * ## PS CONFIG ##  * ###############

 */

static int ltr559_ps_set_thres() {  APS_FUN();

 int res;  u8 databuf[2];     struct i2c_client *client = ltr559_obj->client;   struct ltr559_priv *obj = ltr559_obj;   APS_DBG("ps_cali.valid: %d\n", ps_cali.valid);  if(1 == ps_cali.valid)  {   databuf[0] = LTR559_PS_THRES_LOW_0;   databuf[1] = (u8)(ps_cali.far_away & 0x00FF);   res = i2c_master_send(client, databuf, 0x2);   if(res <= 0)   {    goto EXIT_ERR;    return ltr559_ERR_I2C;   }   databuf[0] = LTR559_PS_THRES_LOW_1;   databuf[1] = (u8)((ps_cali.far_away & 0xFF00) >> 8);   res = i2c_master_send(client, databuf, 0x2);   if(res <= 0)   {    goto EXIT_ERR;    return ltr559_ERR_I2C;   }   databuf[0] = LTR559_PS_THRES_UP_0;    databuf[1] = (u8)(ps_cali.close & 0x00FF);   res = i2c_master_send(client, databuf, 0x2);   if(res <= 0)   {    goto EXIT_ERR;    return ltr559_ERR_I2C;   }   databuf[0] = LTR559_PS_THRES_UP_1;    databuf[1] = (u8)((ps_cali.close & 0xFF00) >> 8);;   res = i2c_master_send(client, databuf, 0x2);   if(res <= 0)   {    goto EXIT_ERR;    return ltr559_ERR_I2C;   }  }  else  {   databuf[0] = LTR559_PS_THRES_LOW_0;   databuf[1] = (u8)((atomic_read(&obj->ps_thd_val_low)) & 0x00FF);   res = i2c_master_send(client, databuf, 0x2);   if(res <= 0)   {    goto EXIT_ERR;    return ltr559_ERR_I2C;   }   databuf[0] = LTR559_PS_THRES_LOW_1;   databuf[1] = (u8)((atomic_read(&obj->ps_thd_val_low )>> 8) & 0x00FF);      res = i2c_master_send(client, databuf, 0x2);   if(res <= 0)   {    goto EXIT_ERR;    return ltr559_ERR_I2C;   }   databuf[0] = LTR559_PS_THRES_UP_0;    databuf[1] = (u8)((atomic_read(&obj->ps_thd_val_high)) & 0x00FF);   res = i2c_master_send(client, databuf, 0x2);   if(res <= 0)   {    goto EXIT_ERR;    return ltr559_ERR_I2C;   }   databuf[0] = LTR559_PS_THRES_UP_1;    databuf[1] = (u8)((atomic_read(&obj->ps_thd_val_high) >> 8) & 0x00FF);   res = i2c_master_send(client, databuf, 0x2);   if(res <= 0)   {    goto EXIT_ERR;    return ltr559_ERR_I2C;   }    }

 res = 0;  return res;    EXIT_ERR:  APS_ERR("set thres: %d\n", res);  return res;

}

static int ltr559_ps_enable(int gainrange) {  struct i2c_client *client = ltr559_obj->client;  struct ltr559_priv *obj = ltr559_obj;  u8 databuf[2];   int res;

 int data;  hwm_sensor_data sensor_data; 

 int error;  int setgain;     APS_LOG("ltr559_ps_enable() ...start!\n");  gainrange = PS_RANGE16;  switch (gainrange) {   case PS_RANGE16:    setgain = MODE_PS_ON_Gain16;    break;

  case PS_RANGE32:    setgain = MODE_PS_ON_Gain32;    break;

  case PS_RANGE64:    setgain = MODE_PS_ON_Gain64;    break;

  default:    setgain = MODE_PS_ON_Gain16;    break;  }

 APS_LOG("LTR559_PS setgain = %d!\n",setgain);

 error = ltr559_i2c_write_reg(LTR559_PS_CONTR, setgain);  if(error<0)  {      APS_LOG("ltr559_ps_enable() error1\n");      return error;  }       //wisky-lxh@20150108  res = ltr559_init_device();  if (res < 0)  {     APS_ERR("ltr559_init_devicet: %d\n", res);   return res;  }  //end-wisky-lxh

     /* ===============   * ** IMPORTANT **   * ===============   * Other settings like timing and threshold to be set here, if required.    * Not set and kept as device default for now.    */

 data = ltr559_i2c_read_reg(LTR559_PS_CONTR);    #ifdef GN_MTK_BSP_PS_DYNAMIC_CALI  //wangxiqiang  if (data & 0x02) {

  if(0 == obj->hw->polling_mode_ps){    mt_eint_mask(CUST_EINT_ALS_NUM);   }      if (ltr559_dynamic_calibrate() < 0)    return -1;  }  #endif 

 /*for interrup work mode support -- by liaoxl.lenovo 12.08.2011*/   if(0 == obj->hw->polling_mode_ps)   {  

   ltr559_ps_set_thres();

   #if 1    databuf[0] = LTR559_INTERRUPT;     databuf[1] = 0x01;    res = i2c_master_send(client, databuf, 0x2);    if(res <= 0)    {     goto EXIT_ERR;     return ltr559_ERR_I2C;    }        databuf[0] = LTR559_INTERRUPT_PERSIST;     databuf[1] = 0x20;    res = i2c_master_send(client, databuf, 0x2);    if(res <= 0)    {     goto EXIT_ERR;     return ltr559_ERR_I2C;    }    mt_eint_unmask(CUST_EINT_ALS_NUM);       #endif     }     APS_LOG("ltr559_ps_enable ...OK!\n");

    return error;

 EXIT_ERR:  APS_ERR("set thres: %d\n", res);  return res; }

// Put PS into Standby mode static int ltr559_ps_disable(void) {  int error;  struct ltr559_priv *obj = ltr559_obj;     error = ltr559_i2c_write_reg(LTR559_PS_CONTR, MODE_PS_StdBy);  if(error<0)       APS_LOG("ltr559_ps_disable ...ERROR\n");   else         APS_LOG("ltr559_ps_disable ...OK\n");

 if(0 == obj->hw->polling_mode_ps)  {      cancel_work_sync(&obj->eint_work);   mt_eint_mask(CUST_EINT_ALS_NUM);  }    return error; }

static int ltr559_ps_read(void) {  int psval_lo, psval_hi, psdata;

 psval_lo = ltr559_i2c_read_reg(LTR559_PS_DATA_0);  APS_DBG("ps_rawdata_psval_lo = %d\n", psval_lo);  if (psval_lo < 0){           APS_DBG("psval_lo error\n");   psdata = psval_lo;   goto out;  }  psval_hi = ltr559_i2c_read_reg(LTR559_PS_DATA_1);     APS_DBG("ps_rawdata_psval_hi = %d\n", psval_hi);

 if (psval_hi < 0){      APS_DBG("psval_hi error\n");   psdata = psval_hi;   goto out;  }    psdata = ((psval_hi & 7)* 256) + psval_lo;     //psdata = ((psval_hi&0x7)<<8) + psval_lo;     APS_DBG("ps_rawdata = %d\n", psdata);

 prox_val = psdata;      out:  final_prox_val = psdata;      return psdata; }

/*  * ################  * ## ALS CONFIG ##  * ################  */

static int ltr559_als_enable(int gainrange) {  int error;  int alsval_ch1_lo,alsval_ch1_hi,alsval_ch1,alsval_ch0_lo,alsval_ch0_hi,alsval_ch0;  gainrange = ALS_RANGE_1300;  APS_LOG("gainrange = %d\n",gainrange);  switch (gainrange)  {   case ALS_RANGE_64K:    error = ltr559_i2c_write_reg(LTR559_ALS_CONTR, MODE_ALS_ON_Range1);    break;

  case ALS_RANGE_32K:    error = ltr559_i2c_write_reg(LTR559_ALS_CONTR, MODE_ALS_ON_Range2);    break;

  case ALS_RANGE_16K:    error = ltr559_i2c_write_reg(LTR559_ALS_CONTR, MODE_ALS_ON_Range3);    break;       case ALS_RANGE_8K:    error = ltr559_i2c_write_reg(LTR559_ALS_CONTR, MODE_ALS_ON_Range4);    break;       case ALS_RANGE_1300:    error = ltr559_i2c_write_reg(LTR559_ALS_CONTR, MODE_ALS_ON_Range5);    break;

  case ALS_RANGE_600:    error = ltr559_i2c_write_reg(LTR559_ALS_CONTR, MODE_ALS_ON_Range6);    break;       default:    error = ltr559_i2c_write_reg(LTR559_ALS_CONTR, MODE_ALS_ON_Range1);       APS_ERR("proxmy sensor gainrange %d!\n", gainrange);    break;  }    ltr559_i2c_read_reg(LTR559_ALS_CONTR);

 mdelay(WAKEUP_DELAY);

 alsval_ch1_lo = ltr559_i2c_read_reg(LTR559_ALS_DATA_CH1_0);  alsval_ch1_hi = ltr559_i2c_read_reg(LTR559_ALS_DATA_CH1_1);  alsval_ch1 = (alsval_ch1_hi * 256) + alsval_ch1_lo;    APS_DBG("enable alsval_ch1_lo = %d,alsval_ch1_hi=%d,alsval_ch1=%d\n",alsval_ch1_lo,alsval_ch1_hi,alsval_ch1);  alsval_ch0_lo = ltr559_i2c_read_reg(LTR559_ALS_DATA_CH0_0);  alsval_ch0_hi = ltr559_i2c_read_reg(LTR559_ALS_DATA_CH0_1);  alsval_ch0 = (alsval_ch0_hi * 256) + alsval_ch0_lo;  APS_DBG("enable alsval_ch0_lo = %d,alsval_ch0_hi=%d,alsval_ch0=%d\n",alsval_ch0_lo,alsval_ch0_hi,alsval_ch0);

  if(error<0)       APS_LOG("ltr559_als_enable ...ERROR\n");   else         APS_LOG("ltr559_als_enable ...OK\n");          return error; }

// Put ALS into Standby mode static int ltr559_als_disable(void) {  int error;  error = ltr559_i2c_write_reg(LTR559_ALS_CONTR, MODE_ALS_StdBy);  if(error<0)       APS_LOG("ltr559_als_disable ...ERROR\n");   else         APS_LOG("ltr559_als_disable ...OK\n");  return error; }

static int ltr559_als_read(int gainrange) {  int alsval_ch0_lo, alsval_ch0_hi, alsval_ch0;  int alsval_ch1_lo, alsval_ch1_hi, alsval_ch1;  int  luxdata_int = -1;  int ratio;  int als_zero_try=0;

als_data_try:

 alsval_ch1_lo = ltr559_i2c_read_reg(LTR559_ALS_DATA_CH1_0);  alsval_ch1_hi = ltr559_i2c_read_reg(LTR559_ALS_DATA_CH1_1);  alsval_ch1 = (alsval_ch1_hi * 256) + alsval_ch1_lo;    APS_DBG("alsval_ch1_lo = %d,alsval_ch1_hi=%d,alsval_ch1=%d\n",alsval_ch1_lo,alsval_ch1_hi,alsval_ch1);  alsval_ch0_lo = ltr559_i2c_read_reg(LTR559_ALS_DATA_CH0_0);  alsval_ch0_hi = ltr559_i2c_read_reg(LTR559_ALS_DATA_CH0_1);  alsval_ch0 = (alsval_ch0_hi * 256) + alsval_ch0_lo;  APS_DBG("alsval_ch0_lo = %d,alsval_ch0_hi=%d,alsval_ch0=%d\n",alsval_ch0_lo,alsval_ch0_hi,alsval_ch0);

    if((alsval_ch1==0)||(alsval_ch0==0))     {      ratio=100;     }else{  ratio = (alsval_ch1*100) /(alsval_ch0+alsval_ch1);     }   APS_DBG("ratio = %d  gainrange = %d\n",ratio,gainrange);  if (ratio < 45){   luxdata_int = (((17743 * alsval_ch0)+(11059 * alsval_ch1)))/10000;  }  else if ((ratio < 64) && (ratio >= 45)){   luxdata_int = (((42785 * alsval_ch0)-(19548 * alsval_ch1)))/10000;  }  else if ((ratio < 100) && (ratio >= 64)) {   luxdata_int = (((5926 * alsval_ch0)+(1185 * alsval_ch1)))/10000;  }  else {   luxdata_int = 0; #if 1     als_zero_try++;   if(als_zero_try < 2){    APS_DBG("als=0, try to find whether is enable for first time.\n");    mdelay(20);    goto als_data_try;   }else{    APS_DBG("als=0.zifan!!!!!!!\n");   } #endif

 }    APS_DBG("als_value_lux = %d\n", luxdata_int);  return luxdata_int;

  err:  final_lux_val = luxdata_int;  APS_DBG("err als_value_lux = 0x%x\n", luxdata_int);  return luxdata_int; }

 

/*----------------------------------------------------------------------------*/ int ltr559_get_addr(struct alsps_hw *hw, struct ltr559_i2c_addr *addr) {  /***  if(!hw || !addr)  {   return -EFAULT;  }  addr->write_addr= hw->i2c_addr[0];  ***/  return 0; }

/*-----------------------------------------------------------------------------*/ void ltr559_eint_func(void) {  APS_FUN();

 struct ltr559_priv *obj = ltr559_obj;  if(!obj)  {   return;  }    schedule_work(&obj->eint_work);  //schedule_delayed_work(&obj->eint_work); }

 

/*----------------------------------------------------------------------------*/ /*for interrup work mode support -- by liaoxl.lenovo 12.08.2011*/ int ltr559_setup_eint(struct i2c_client *client) {  APS_FUN();  struct ltr559_priv *obj = (struct ltr559_priv *)i2c_get_clientdata(client);       

 ltr559_obj = obj;  mt_set_gpio_dir(GPIO_ALS_EINT_PIN, GPIO_DIR_IN);  mt_set_gpio_mode(GPIO_ALS_EINT_PIN, GPIO_ALS_EINT_PIN_M_EINT);  mt_set_gpio_pull_enable(GPIO_ALS_EINT_PIN, TRUE);  mt_set_gpio_pull_select(GPIO_ALS_EINT_PIN, GPIO_PULL_UP);

 mt_eint_set_hw_debounce(CUST_EINT_ALS_NUM, CUST_EINT_ALS_DEBOUNCE_CN);  mt_eint_registration(CUST_EINT_ALS_NUM, CUST_EINT_ALS_TYPE, ltr559_eint_func, 0);  mt_eint_unmask(CUST_EINT_ALS_NUM);      return 0; }

/*----------------------------------------------------------------------------*/ static void ltr559_power(struct alsps_hw *hw, unsigned int on) {  static unsigned int power_on = 0;

 //APS_LOG("power %s\n", on ? "on" : "off");

 if(hw->power_id != POWER_NONE_MACRO)  {   if(power_on == on)   {    APS_LOG("ignore power control: %d\n", on);   }   else if(on)   {    if(!hwPowerOn(hw->power_id, hw->power_vol, "LTR559"))    {     APS_ERR("power on fails!!\n");    }   }   else   {    if(!hwPowerDown(hw->power_id, "LTR559"))    {     APS_ERR("power off fail!!\n");      }   }  }  power_on = on; }

/*----------------------------------------------------------------------------*/ /*for interrup work mode support -- by liaoxl.lenovo 12.08.2011*/ static int ltr559_check_and_clear_intr(struct i2c_client *client) { //***  APS_FUN();

 int res,intp,intl;  u8 buffer[2];   u8 temp;   //if (mt_get_gpio_in(GPIO_ALS_EINT_PIN) == 1) /*skip if no interrupt*/    //   return 0;     buffer[0] = LTR559_ALS_PS_STATUS;   res = i2c_master_send(client, buffer, 0x1);   if(res <= 0)   {    goto EXIT_ERR;   }   res = i2c_master_recv(client, buffer, 0x1);   if(res <= 0)   {    goto EXIT_ERR;   }   temp = buffer[0];   res = 1;   intp = 0;   intl = 0;   if(0 != (buffer[0] & 0x02))   {    res = 0;    intp = 1;   }   if(0 != (buffer[0] & 0x08))   {    res = 0;    intl = 1;     }     if(0 == res)   {    if((1 == intp) && (0 == intl))    {     buffer[1] = buffer[0] & 0xfD;         }    else if((0 == intp) && (1 == intl))    {     buffer[1] = buffer[0] & 0xf7;    }    else    {     buffer[1] = buffer[0] & 0xf5;    }    buffer[0] = LTR559_ALS_PS_STATUS ;    res = i2c_master_send(client, buffer, 0x2);    if(res <= 0)    {     goto EXIT_ERR;    }    else    {     res = 0;    }   }     return res;    EXIT_ERR:   APS_ERR("ltr559_check_and_clear_intr fail\n");   return 1;

} /*----------------------------------------------------------------------------*/

static int ltr559_check_intr(struct i2c_client *client) {  APS_FUN();

 int res,intp,intl;  u8 buffer[2];

 //if (mt_get_gpio_in(GPIO_ALS_EINT_PIN) == 1) /*skip if no interrupt*/   //    return 0;

 buffer[0] = LTR559_ALS_PS_STATUS;  res = i2c_master_send(client, buffer, 0x1);  if(res <= 0)  {   goto EXIT_ERR;  }  res = i2c_master_recv(client, buffer, 0x1);  if(res <= 0)  {   goto EXIT_ERR;  }  res = 1;  intp = 0;  intl = 0;  if(0 != (buffer[0] & 0x02))  {   res = 0; //Ps int   intp = 1;  }  if(0 != (buffer[0] & 0x08))  {   res = 0;   intl = 1;    }

 return res;

EXIT_ERR:  APS_ERR("ltr559_check_intr fail\n");  return 1; }

static int ltr559_clear_intr(struct i2c_client *client) {  int res;  u8 buffer[2];

 APS_FUN();    buffer[0] = LTR559_ALS_PS_STATUS;  res = i2c_master_send(client, buffer, 0x1);  if(res <= 0)  {   goto EXIT_ERR;  }  res = i2c_master_recv(client, buffer, 0x1);  if(res <= 0)  {   goto EXIT_ERR;  }  APS_DBG("buffer[0] = %d \n",buffer[0]);  buffer[1] = buffer[0] & 0x01;  buffer[0] = LTR559_ALS_PS_STATUS ;

 res = i2c_master_send(client, buffer, 0x2);  if(res <= 0)  {   goto EXIT_ERR;  }  else  {   res = 0;  }

 return res;

EXIT_ERR:  APS_ERR("ltr559_check_and_clear_intr fail\n");  return 1; }

//wisky-lxh@20150108 static int ltr559_init_device(void) {     int error = 0;

 error = ltr559_i2c_write_reg(LTR559_PS_LED, 0x7F);  if(error<0)     {         APS_LOG("ltr559_ps_enable() error3...\n");      return error;  }       error = ltr559_i2c_write_reg(LTR559_PS_N_PULSES, 0x06);  if(error<0)     {         APS_LOG("ltr559_ps_enable() error2\n");      return error;  }

    error = ltr559_i2c_write_reg(LTR559_ALS_MEAS_RATE, 0x08);     if(error<0)     {         APS_LOG("ltr559_ps_enable() error2\n");         return error;     }

    error = ltr559_i2c_write_reg(LTR559_PS_MEAS_RATE, 0x01);     if(error<0)     {         APS_LOG("ltr559_ps_enable() error2\n");         return error;     }  

    error = ltr559_i2c_write_reg(LTR559_PS_THRES_UP_0, ps_trigger_high & 0xff);     if(error<0)     {         APS_LOG("ltr559_ps_enable() error2\n");         return error;     }     error = ltr559_i2c_write_reg(LTR559_PS_THRES_UP_1, (ps_trigger_high>>8) & 0X07);     if(error<0)     {         APS_LOG("ltr559_ps_enable() error2\n");         return error;     }     error = ltr559_i2c_write_reg(LTR559_PS_THRES_LOW_0, 0x0);     if(error<0)     {         APS_LOG("ltr559_ps_enable() error2\n");         return error;     }     error = ltr559_i2c_write_reg(LTR559_PS_THRES_LOW_1, 0x0);     if(error<0)     {         APS_LOG("ltr559_ps_enable() error2\n");         return error;     }

    mdelay(WAKEUP_DELAY);

    return error;

} //end-wisky-lxh

static int ltr559_devinit(void) {  int res;  int init_ps_gain;  int init_als_gain;  u8 databuf[2]; 

 struct i2c_client *client = ltr559_obj->client;

 struct ltr559_priv *obj = ltr559_obj;      mdelay(PON_DELAY);

 //soft reset when device init add by steven  databuf[0] = LTR559_ALS_CONTR;   databuf[1] = 0x02;  res = i2c_master_send(client, databuf, 0x2);  if(res <= 0)  {   goto EXIT_ERR;   return ltr559_ERR_I2C;  }

 /*for interrup work mode support */  if(0 == obj->hw->polling_mode_ps)  {    APS_LOG("eint enable");   ltr559_ps_set_thres();      databuf[0] = LTR559_INTERRUPT;    databuf[1] = 0x01;   res = i2c_master_send(client, databuf, 0x2);   if(res <= 0)   {    goto EXIT_ERR;    return ltr559_ERR_I2C;   }

  databuf[0] = LTR559_INTERRUPT_PERSIST;    databuf[1] = 0x20;   res = i2c_master_send(client, databuf, 0x2);   if(res <= 0)   {    goto EXIT_ERR;    return ltr559_ERR_I2C;   }

 }

 if((res = ltr559_setup_eint(client))!=0)  {   APS_ERR("setup eint: %d\n", res);   return res;  }     //wisky-lxh@20150108  res = ltr559_init_device();  if (res < 0)  {     APS_ERR("ltr559_init_devicet: %d\n", res);   return res;  }  //end-wisky-lxh  if((res = ltr559_check_and_clear_intr(client)))  {   APS_ERR("check/clear intr: %d\n", res);   //    return res;  }

 res = 0;

 EXIT_ERR:  APS_ERR("init dev: %d\n", res);  return res;

} /*----------------------------------------------------------------------------*/

static int ltr559_get_als_value(struct ltr559_priv *obj, u16 als) {  int idx;  int invalid = 0;  APS_DBG("als  = %d\n",als);  for(idx = 0; idx < obj->als_level_num; idx++)  {   if(als < obj->hw->als_level[idx])   {    break;   }  }    if(idx >= obj->als_value_num)  {   APS_ERR("exceed range\n");   idx = obj->als_value_num - 1;  }    if(1 == atomic_read(&obj->als_deb_on))  {   unsigned long endt = atomic_read(&obj->als_deb_end);   if(time_after(jiffies, endt))   {    atomic_set(&obj->als_deb_on, 0);   }      if(1 == atomic_read(&obj->als_deb_on))   {    invalid = 1;   }  }

 if(!invalid)  {   APS_DBG("ALS: %05d => %05d\n", als, obj->hw->als_value[idx]);    return obj->hw->als_value[idx];  }  else  {   APS_ERR("ALS: %05d => %05d (-1)\n", als, obj->hw->als_value[idx]);      return -1;  } } /*----------------------------------------------------------------------------*/ static int ltr559_get_ps_value(struct ltr559_priv *obj, u16 ps) {  int val,  mask = atomic_read(&obj->ps_mask);  int invalid = 0;

 static int val_temp = 5;  if((ps > atomic_read(&obj->ps_thd_val_high)))  {   val = 0;  /*close*/   val_temp = 0;   intr_flag_value = 1;   gesture_notifier_call_chain(1,NULL); //add by chen gesture  }    //else if((ps < atomic_read(&obj->ps_thd_val_low))&&(temp_ps[0]  < atomic_read(&obj->ps_thd_val_low)))  else if((ps < atomic_read(&obj->ps_thd_val_low)))  {   val = 5;  /*far away*/   val_temp = 5;   intr_flag_value = 0;   gesture_notifier_call_chain(0,NULL); //add by chen gesture  }  else   val = val_temp;         if(atomic_read(&obj->ps_suspend))  {   invalid = 1;  }  else if(1 == atomic_read(&obj->ps_deb_on))  {   unsigned long endt = atomic_read(&obj->ps_deb_end);   if(time_after(jiffies, endt))   {    atomic_set(&obj->ps_deb_on, 0);   }      if (1 == atomic_read(&obj->ps_deb_on))   {    invalid = 1;   }  }  else if (obj->als > 50000)  {   //invalid = 1;   APS_DBG("ligh too high will result to failt proximiy\n");   return 1;  /*far away*/  }

 if(!invalid)  {   APS_DBG("PS:  %05d => %05d\n", ps, val);   return val;  }   else  {   return -1;  }  }

/*----------------------------------------------------------------------------*/

/*----------------------------------------------------------------------------*/ /*for interrup work mode support */ static void ltr559_eint_work(struct work_struct *work) {  struct ltr559_priv *obj = (struct ltr559_priv *)container_of(work, struct ltr559_priv, eint_work);  int err;  hwm_sensor_data sensor_data;  int temp_noise;  // u8 buffer[1]; // u8 reg_value[1];  u8 databuf[2];  int res = 0;  APS_FUN();  err = ltr559_check_intr(obj->client);  if(err < 0)  {   APS_ERR("ltr559_eint_work check intrs: %d\n", err);  }  else  {   //get raw data   obj->ps = ltr559_ps_read();      if(obj->ps < 0)      {       err = -1;       return;      }        APS_DBG("ltr559_eint_work rawdata ps=%d als_ch0=%d!\n",obj->ps,obj->als);   sensor_data.values[0] = ltr559_get_ps_value(obj, obj->ps);   //sensor_data.values[1] = obj->ps;   sensor_data.value_divide = 1;   sensor_data.status = SENSOR_STATUS_ACCURACY_MEDIUM;    /*singal interrupt function add*/   APS_DBG("intr_flag_value=%d\n",intr_flag_value);   if(intr_flag_value){    APS_DBG(" interrupt value ps will < ps_threshold_low");

   databuf[0] = LTR559_PS_THRES_LOW_0;     databuf[1] = (u8)((atomic_read(&obj->ps_thd_val_low)) & 0x00FF);    res = i2c_master_send(obj->client, databuf, 0x2);    if(res <= 0)    {     return;    }    databuf[0] = LTR559_PS_THRES_LOW_1;     databuf[1] = (u8)(((atomic_read(&obj->ps_thd_val_low)) & 0xFF00) >> 8);    res = i2c_master_send(obj->client, databuf, 0x2);    if(res <= 0)    {     return;    }    databuf[0] = LTR559_PS_THRES_UP_0;     databuf[1] = (u8)(0x00FF);    res = i2c_master_send(obj->client, databuf, 0x2);    if(res <= 0)    {     return;    }    databuf[0] = LTR559_PS_THRES_UP_1;    databuf[1] = (u8)((0xFF00) >> 8);;    res = i2c_master_send(obj->client, databuf, 0x2);    //APS_DBG("obj->ps_thd_val_low=%ld !\n",obj->ps_thd_val_low);    if(res <= 0)    {     return;    }   }   else{          //if(obj->ps > 20 && obj->ps < (dynamic_calibrate - 50)){ //wangxiqiang    //if(obj->ps > 20){      if(obj->ps < 100){        atomic_set(&obj->ps_thd_val_high,  obj->ps+80);     atomic_set(&obj->ps_thd_val_low, obj->ps+60);    }else if(obj->ps < 200){     atomic_set(&obj->ps_thd_val_high,  obj->ps+100);     atomic_set(&obj->ps_thd_val_low, obj->ps+80);    }else if(obj->ps < 300){     atomic_set(&obj->ps_thd_val_high,  obj->ps+100);     atomic_set(&obj->ps_thd_val_low, obj->ps+80);    }else if(obj->ps < 400){     atomic_set(&obj->ps_thd_val_high,  obj->ps+100);     atomic_set(&obj->ps_thd_val_low, obj->ps+80);    }else if(obj->ps < 600){     atomic_set(&obj->ps_thd_val_high,  obj->ps+180);     atomic_set(&obj->ps_thd_val_low, obj->ps+90);    }else if(obj->ps < 1000){     atomic_set(&obj->ps_thd_val_high,  obj->ps+300);     atomic_set(&obj->ps_thd_val_low, obj->ps+180);     }else if(obj->ps < 1250){     atomic_set(&obj->ps_thd_val_high,  obj->ps+400);     atomic_set(&obj->ps_thd_val_low, obj->ps+300);    }    else{     atomic_set(&obj->ps_thd_val_high,  1300);     atomic_set(&obj->ps_thd_val_low, 1000);     printk(KERN_ERR "ltr559 the proximity sensor structure is error\n");    }       dynamic_calibrate = obj->ps;

   //} 

   if(obj->ps > 50){     temp_noise = obj->ps - 50;    }else{     temp_noise = 0;    }

   //wake_lock_timeout(&ps_wake_lock,ps_wakeup_timeout*HZ);    databuf[0] = LTR559_PS_THRES_LOW_0;    databuf[1] = (u8)(0 & 0x00FF);//get the noise one time    res = i2c_master_send(obj->client, databuf, 0x2);    if(res <= 0)    {     return;    }    databuf[0] = LTR559_PS_THRES_LOW_1;    databuf[1] = (u8)((0 & 0xFF00) >> 8);    res = i2c_master_send(obj->client, databuf, 0x2);    if(res <= 0)    {     return;    }    databuf[0] = LTR559_PS_THRES_UP_0;     databuf[1] = (u8)((atomic_read(&obj->ps_thd_val_high)) & 0x00FF);    res = i2c_master_send(obj->client, databuf, 0x2);    if(res <= 0)    {     return;    }    databuf[0] = LTR559_PS_THRES_UP_1;    databuf[1] = (u8)(((atomic_read(&obj->ps_thd_val_high)) & 0xFF00) >> 8);;    res = i2c_master_send(obj->client, databuf, 0x2); //   APS_DBG("obj->ps_thd_val_high=%ld !\n",obj->ps_thd_val_high);    if(res <= 0)    {     return;    }   }      sensor_data.value_divide = 1;   sensor_data.status = SENSOR_STATUS_ACCURACY_MEDIUM;   //let up layer to know   if((err = hwmsen_get_interrupt_data(ID_PROXIMITY, &sensor_data)))   {     APS_ERR("call hwmsen_get_interrupt_data fail = %d\n", err);   }  }  ltr559_clear_intr(obj->client);     mt_eint_unmask(CUST_EINT_ALS_NUM);       }

 

/******************************************************************************  * Function Configuration ******************************************************************************/ static int ltr559_open(struct inode *inode, struct file *file) {  file->private_data = ltr559_i2c_client;

 if (!file->private_data)  {   APS_ERR("null pointer!!\n");   return -EINVAL;  }    return nonseekable_open(inode, file); } /*----------------------------------------------------------------------------*/ static int ltr559_release(struct inode *inode, struct file *file) {  file->private_data = NULL;  return 0; } /*----------------------------------------------------------------------------*/

static int ltr559_unlocked_ioctl(struct file *file, unsigned int cmd,        unsigned long arg)       {  struct i2c_client *client = (struct i2c_client*)file->private_data;  struct ltr559_priv *obj = i2c_get_clientdata(client);   int err = 0;  void __user *ptr = (void __user*) arg;  int dat;  uint32_t enable;  APS_DBG("ltr559_unlocked_ioctl cmd= %d\n", cmd);  switch (cmd)  {   case ALSPS_SET_PS_MODE:    if(copy_from_user(&enable, ptr, sizeof(enable)))    {     err = -EFAULT;     goto err_out;    }    if(enable)    {        err = ltr559_ps_enable(ps_gainrange);     if(err < 0)     {      APS_ERR("enable ps fail: %d\n", err);      goto err_out;     }     set_bit(CMC_BIT_PS, &obj->enable);    }    else    {        err = ltr559_ps_disable();     if(err < 0)     {      APS_ERR("disable ps fail: %d\n", err);      goto err_out;     }          clear_bit(CMC_BIT_PS, &obj->enable);    }    break;

  case ALSPS_GET_PS_MODE:    enable = test_bit(CMC_BIT_PS, &obj->enable) ? (1) : (0);    if(copy_to_user(ptr, &enable, sizeof(enable)))    {     err = -EFAULT;     goto err_out;    }    break;

  case ALSPS_GET_PS_DATA:    APS_DBG("ALSPS_GET_PS_DATA\n");       obj->ps = ltr559_ps_read();    if(obj->ps < 0)    {     goto err_out;    }        dat = ltr559_get_ps_value(obj, obj->ps);    if(copy_to_user(ptr, &dat, sizeof(dat)))    {     err = -EFAULT;     goto err_out;    }     break;

  case ALSPS_GET_PS_RAW_DATA:        #if 1    obj->ps = ltr559_ps_read();    if(obj->ps < 0)    {     goto err_out;    }    dat = obj->ps;    #endif

   //dat = prox_val;  //read static variate        if(copy_to_user(ptr, &dat, sizeof(dat)))    {     err = -EFAULT;     goto err_out;    }     break;

  case ALSPS_SET_ALS_MODE:    if(copy_from_user(&enable, ptr, sizeof(enable)))    {     err = -EFAULT;     goto err_out;    }    if(enable)    {        err = ltr559_als_enable(als_gainrange);     if(err < 0)     {      APS_ERR("enable als fail: %d\n", err);      goto err_out;     }     set_bit(CMC_BIT_ALS, &obj->enable);    }    else    {        err = ltr559_als_disable();     if(err < 0)     {      APS_ERR("disable als fail: %d\n", err);      goto err_out;     }     clear_bit(CMC_BIT_ALS, &obj->enable);    }    break;

  case ALSPS_GET_ALS_MODE:    enable = test_bit(CMC_BIT_ALS, &obj->enable) ? (1) : (0);    if(copy_to_user(ptr, &enable, sizeof(enable)))    {     err = -EFAULT;     goto err_out;    }    break;

  case ALSPS_GET_ALS_DATA:       obj->als = ltr559_als_read(als_gainrange);    if(obj->als < 0)    {     goto err_out;    }

   dat = ltr559_get_als_value(obj, obj->als);    if(copy_to_user(ptr, &dat, sizeof(dat)))    {     err = -EFAULT;     goto err_out;    }                 break;

  case ALSPS_GET_ALS_RAW_DATA:       obj->als = ltr559_als_read(als_gainrange);    if(obj->als < 0)    {     goto err_out;    }

   dat = obj->als;    if(copy_to_user(ptr, &dat, sizeof(dat)))    {     err = -EFAULT;     goto err_out;    }                 break;

  default:    APS_ERR("%s not supported = 0x%04x", __FUNCTION__, cmd);    err = -ENOIOCTLCMD;    break;  }

 err_out:  return err;    }

/*----------------------------------------------------------------------------*/ static struct file_operations ltr559_fops = {  //.owner = THIS_MODULE,  .open = ltr559_open,  .release = ltr559_release,  .unlocked_ioctl = ltr559_unlocked_ioctl, }; /*----------------------------------------------------------------------------*/ static struct miscdevice ltr559_device = {  .minor = MISC_DYNAMIC_MINOR,  .name = "als_ps",  .fops = &ltr559_fops, };

static int ltr559_i2c_suspend(struct i2c_client *client, pm_message_t msg) {  struct ltr559_priv *obj = i2c_get_clientdata(client);     int err;  APS_FUN();   

 if(msg.event == PM_EVENT_SUSPEND)  {     if(!obj)   {    APS_ERR("null pointer!!\n");    return -EINVAL;   }      atomic_set(&obj->als_suspend, 1);   err = ltr559_als_disable();   if(err < 0)   {    APS_ERR("disable als: %d\n", err);    return err;   }

  #if 0  //suspend not need ps suspend  not need power down   atomic_set(&obj->ps_suspend, 1);   err = ltr559_ps_disable();   if(err < 0)   {    APS_ERR("disable ps:  %d\n", err);    return err;   }        ltr559_power(obj->hw, 0);

  #endif  }  return 0; } /*----------------------------------------------------------------------------*/ static int ltr559_i2c_resume(struct i2c_client *client) {  struct ltr559_priv *obj = i2c_get_clientdata(client);         int err;  err = 0;  APS_FUN();

 if(!obj)  {   APS_ERR("null pointer!!\n");   return -EINVAL;  }

 ltr559_power(obj->hw, 1); /* err = ltr559_devinit();  if(err < 0)  {   APS_ERR("initialize client fail!!\n");   return err;         }*/  atomic_set(&obj->als_suspend, 0);  if(test_bit(CMC_BIT_ALS, &obj->enable))  {      err = ltr559_als_enable(als_gainrange);      if (err < 0)   {    APS_ERR("enable als fail: %d\n", err);          }  }  //atomic_set(&obj->ps_suspend, 0);  if(test_bit(CMC_BIT_PS,  &obj->enable))  {   //err = ltr559_ps_enable(ps_gainrange);      if (err < 0)   {    APS_ERR("enable ps fail: %d\n", err);                  }  }

 return 0; }

static void ltr559_early_suspend(struct early_suspend *h) {   /*early_suspend is only applied for ALS*/  struct ltr559_priv *obj = container_of(h, struct ltr559_priv, early_drv);    int err;  APS_FUN();   

 if(!obj)  {   APS_ERR("null pointer!!\n");   return;  }    atomic_set(&obj->als_suspend, 1);  err = ltr559_als_disable();  if(err < 0)  {   APS_ERR("disable als fail: %d\n", err);  } }

static void ltr559_late_resume(struct early_suspend *h) {   /*early_suspend is only applied for ALS*/  struct ltr559_priv *obj = container_of(h, struct ltr559_priv, early_drv);          int err;  APS_FUN();

 if(!obj)  {   APS_ERR("null pointer!!\n");   return;  }

 atomic_set(&obj->als_suspend, 0);  if(test_bit(CMC_BIT_ALS, &obj->enable))  {      err = ltr559_als_enable(als_gainrange);   if(err < 0)   {    APS_ERR("enable als fail: %d\n", err);       

  }  } }

int ltr559_ps_operate(void* self, uint32_t command, void* buff_in, int size_in,   void* buff_out, int size_out, int* actualout) {  int err = 0;  int value;  hwm_sensor_data* sensor_data;  struct ltr559_priv *obj = (struct ltr559_priv *)self;    switch (command)  {   case SENSOR_DELAY:    if((buff_in == NULL) || (size_in < sizeof(int)))    {     APS_ERR("Set delay parameter error!\n");     err = -EINVAL;    }    // Do nothing    break;

  case SENSOR_ENABLE:    if((buff_in == NULL) || (size_in < sizeof(int)))    {     APS_ERR("Enable sensor parameter error!\n");     err = -EINVAL;    }    else    {         value = *(int *)buff_in;     if(value)     {         err = ltr559_ps_enable(ps_gainrange);      if(err < 0)      {       APS_ERR("enable ps fail: %d\n", err);       return -1;      }      set_bit(CMC_BIT_PS, &obj->enable);     }     else     {         err = ltr559_ps_disable();      if(err < 0)      {       APS_ERR("disable ps fail: %d\n", err);       return -1;      }      clear_bit(CMC_BIT_PS, &obj->enable);     }    }    break;

  case SENSOR_GET_DATA:    if((buff_out == NULL) || (size_out< sizeof(hwm_sensor_data)))    {     APS_ERR("get sensor data parameter error!\n");     err = -EINVAL;    }    else    {     APS_ERR("get sensor ps data !\n");     sensor_data = (hwm_sensor_data *)buff_out;     obj->ps = ltr559_ps_read();        if(obj->ps < 0)        {         err = -1;         break;        }     sensor_data->values[0] = ltr559_get_ps_value(obj, obj->ps);     //sensor_data->values[1] = obj->ps;  //steven polling mode *#*#3646633#*#*     sensor_data->value_divide = 1;     sensor_data->status = SENSOR_STATUS_ACCURACY_MEDIUM;       }    break;   default:    APS_ERR("proxmy sensor operate function no this parameter %d!\n", command);    err = -1;    break;  }    return err; }

int ltr559_als_operate(void* self, uint32_t command, void* buff_in, int size_in,   void* buff_out, int size_out, int* actualout) {  int err = 0;  int value;  hwm_sensor_data* sensor_data;  struct ltr559_priv *obj = (struct ltr559_priv *)self;

 switch (command)  {   case SENSOR_DELAY:    if((buff_in == NULL) || (size_in < sizeof(int)))    {     APS_ERR("Set delay parameter error!\n");     err = -EINVAL;    }    // Do nothing    break;

  case SENSOR_ENABLE:    if((buff_in == NULL) || (size_in < sizeof(int)))    {     APS_ERR("Enable sensor parameter error!\n");     err = -EINVAL;    }    else    {     value = *(int *)buff_in;         if(value)     {         err = ltr559_als_enable(als_gainrange);      if(err < 0)      {       APS_ERR("enable als fail: %d\n", err);       return -1;      }      set_bit(CMC_BIT_ALS, &obj->enable);     }     else     {         err = ltr559_als_disable();      if(err < 0)      {       APS_ERR("disable als fail: %d\n", err);       return -1;      }      clear_bit(CMC_BIT_ALS, &obj->enable);     }         }    break;

  case SENSOR_GET_DATA:    if((buff_out == NULL) || (size_out< sizeof(hwm_sensor_data)))    {     APS_ERR("get sensor data parameter error!\n");     err = -EINVAL;    }    else    {     APS_ERR("get sensor als data !\n");     sensor_data = (hwm_sensor_data *)buff_out;     obj->als = ltr559_als_read(als_gainrange);                 #if defined(MTK_AAL_SUPPORT)     sensor_data->values[0] = ltr559_get_als_value(obj, obj->als);//wisky-lxh@20150206     #else     sensor_data->values[0] = ltr559_get_als_value(obj, obj->als);     #endif     sensor_data->value_divide = 1;     sensor_data->status = SENSOR_STATUS_ACCURACY_MEDIUM;    }    break;   default:    APS_ERR("light sensor operate function no this parameter %d!\n", command);    err = -1;    break;  }    return err; }

/*----------------------------------------------------------------------------*/ static int ltr559_i2c_detect(struct i2c_client *client, int kind, struct i2c_board_info *info) {     strcpy(info->type, LTR559_DEV_NAME);  return 0; }

/*----------------------------------------------------------------------------*/ static int ltr559_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) {  struct ltr559_priv *obj;  struct hwmsen_object obj_ps, obj_als;  int err = 0;

 if(!(obj = kzalloc(sizeof(*obj), GFP_KERNEL)))  {   err = -ENOMEM;   goto exit;  }  memset(obj, 0, sizeof(*obj));  ltr559_obj = obj;

 obj->hw = get_cust_alsps_hw();  ltr559_get_addr(obj->hw, &obj->addr);

 INIT_WORK(&obj->eint_work, ltr559_eint_work);  obj->client = client;  i2c_set_clientdata(client, obj);   atomic_set(&obj->als_debounce, 300);  atomic_set(&obj->als_deb_on, 0);  atomic_set(&obj->als_deb_end, 0);  atomic_set(&obj->ps_debounce, 300);  atomic_set(&obj->ps_deb_on, 0);  atomic_set(&obj->ps_deb_end, 0);  atomic_set(&obj->ps_mask, 0);  atomic_set(&obj->als_suspend, 0);  atomic_set(&obj->ps_thd_val_high,  obj->hw->ps_threshold_high);  atomic_set(&obj->ps_thd_val_low,  obj->hw->ps_threshold_low);  //atomic_set(&obj->als_cmd_val, 0xDF);  //atomic_set(&obj->ps_cmd_val,  0xC1);  atomic_set(&obj->ps_thd_val,  obj->hw->ps_threshold);  obj->enable = 0;  obj->pending_intr = 0;  obj->als_level_num = sizeof(obj->hw->als_level)/sizeof(obj->hw->als_level[0]);  obj->als_value_num = sizeof(obj->hw->als_value)/sizeof(obj->hw->als_value[0]);    obj->als_modulus = (400*100)/(16*150);//(1/Gain)*(400/Tine), this value is fix after init ATIME and CONTROL register value           //(400)/16*2.72 here is amplify *100  BUG_ON(sizeof(obj->als_level) != sizeof(obj->hw->als_level));  memcpy(obj->als_level, obj->hw->als_level, sizeof(obj->als_level));  BUG_ON(sizeof(obj->als_value) != sizeof(obj->hw->als_value));  memcpy(obj->als_value, obj->hw->als_value, sizeof(obj->als_value));  atomic_set(&obj->i2c_retry, 3);  set_bit(CMC_BIT_ALS, &obj->enable);  set_bit(CMC_BIT_PS, &obj->enable);

 APS_LOG("ltr559_devinit() start...!\n");  ltr559_i2c_client = client;

 if(err = ltr559_devinit())  {   goto exit_init_failed;  }  APS_LOG("ltr559_devinit() ...OK!\n");

 //printk("@@@@@@ manufacturer value:%x\n",ltr559_i2c_read_reg(0x87));

 if(err = misc_register(&ltr559_device))  {   APS_ERR("ltr559_device register failed\n");   goto exit_misc_device_register_failed;  }

   /* Register sysfs attribute */  if(err = ltr559_create_attr(&ltr559_alsps_driver.driver))  {   printk(KERN_ERR "create attribute err = %d\n", err);   goto exit_create_attr_failed;  }

 obj_ps.self = ltr559_obj;  /*for interrup work mode support -- by liaoxl.lenovo 12.08.2011*/  if(1 == obj->hw->polling_mode_ps)  {   obj_ps.polling = 1;  }  else  {   obj_ps.polling = 0;  }  obj_ps.sensor_operate = ltr559_ps_operate;  if(err = hwmsen_attach(ID_PROXIMITY, &obj_ps))  {   APS_ERR("attach fail = %d\n", err);   goto exit_create_attr_failed;  }    obj_als.self = ltr559_obj;  obj_als.polling = 1;  obj_als.sensor_operate = ltr559_als_operate;  if(err = hwmsen_attach(ID_LIGHT, &obj_als))  {   APS_ERR("attach fail = %d\n", err);   goto exit_create_attr_failed;  }

#if defined(CONFIG_HAS_EARLYSUSPEND)  obj->early_drv.level    = EARLY_SUSPEND_LEVEL_DISABLE_FB - 1,  obj->early_drv.suspend  = ltr559_early_suspend,  obj->early_drv.resume   = ltr559_late_resume,     register_early_suspend(&obj->early_drv); #endif

 APS_LOG("%s: OK\n", __func__);  return 0;  exit_create_attr_failed:  misc_deregister(&ltr559_device);  exit_misc_device_register_failed:  exit_init_failed:  //i2c_detach_client(client);  exit_kfree:  kfree(obj);  exit:  ltr559_i2c_client = NULL;           // MT6516_EINTIRQMask(CUST_EINT_ALS_NUM);  /*mask interrupt if fail*/  APS_ERR("%s: err = %d\n", __func__, err);  return err; }

/*----------------------------------------------------------------------------*/

static int ltr559_i2c_remove(struct i2c_client *client) {  int err;   if(err = ltr559_delete_attr(&ltr559_i2c_driver.driver))  {   APS_ERR("ltr559_delete_attr fail: %d\n", err);  }

 if(err = misc_deregister(&ltr559_device))  {   APS_ERR("misc_deregister fail: %d\n", err);     }    ltr559_i2c_client = NULL;  i2c_unregister_device(client);  kfree(i2c_get_clientdata(client));

 return 0; } /*----------------------------------------------------------------------------*/ static int ltr559_probe(struct platform_device *pdev) {  struct alsps_hw *hw = get_cust_alsps_hw();

 ltr559_power(hw, 1);  //ltr559_force[0] = hw->i2c_num;  //ltr559_force[1] = hw->i2c_addr[0];  //APS_DBG("I2C = %d, addr =0x%x\n",ltr559_force[0],ltr559_force[1]);  if(i2c_add_driver(&ltr559_i2c_driver))  {   APS_ERR("add driver error\n");   return -1;  }  return 0; } /*----------------------------------------------------------------------------*/ static int ltr559_remove(struct platform_device *pdev) {  struct alsps_hw *hw = get_cust_alsps_hw();  APS_FUN();     ltr559_power(hw, 0);     i2c_del_driver(&ltr559_i2c_driver);  return 0; } /*----------------------------------------------------------------------------*/

#ifdef CONFIG_OF static const struct of_device_id alsps_of_match[] = {  { .compatible = "mediatek,als_ps", },  {}, }; #endif

static struct platform_driver ltr559_alsps_driver = {  .probe      = ltr559_probe,  .remove     = ltr559_remove,     .driver     =  {   .name = "als_ps",   .owner  = THIS_MODULE,         #ifdef CONFIG_OF   .of_match_table = alsps_of_match,   #endif  } };

#ifdef CONFIG_OF static struct platform_device ltr559_alsps_device={  .name="als_ps",  .id=-1 }; #endif

/*----------------------------------------------------------------------------*/ static int __init ltr559_init(void) {        struct alsps_hw *hw = get_cust_alsps_hw();  APS_FUN();    i2c_register_board_info(hw->i2c_num, &i2c_ltr559, 1);  

 if(platform_driver_register(&ltr559_alsps_driver))  {   APS_ERR("failed to register driver");   return -ENODEV;  }  return 0; } /*----------------------------------------------------------------------------*/ static void __exit ltr559_exit(void) {  APS_FUN();  platform_driver_unregister(&ltr559_alsps_driver); } /*----------------------------------------------------------------------------*/ module_init(ltr559_init); module_exit(ltr559_exit); /*----------------------------------------------------------------------------*/ MODULE_AUTHOR("XX Xx"); MODULE_DESCRIPTION("LTR-559ALS Driver"); MODULE_LICENSE("GPL");

 

gt9xx_driver.c_new

#include "tpd.h" #include "tpd_custom_gt9xx.h"

#ifndef TPD_NO_GPIO #include "cust_gpio_usage.h" #endif #ifdef TPD_PROXIMITY #include <linux/hwmsensor.h> #include <linux/hwmsen_dev.h> #include <linux/sensors_io.h> #endif

#ifdef CONFIG_OF_TOUCH #include <linux/of.h> #include <linux/of_irq.h> #endif

#if GTP_SUPPORT_I2C_DMA     #include <linux/dma-mapping.h> #endif

#ifdef CONFIG_OF_TOUCH static int irq_flag; static unsigned int touch_irq = 0; #endif

extern char tp_info[20];

extern struct tpd_device *tpd; extern u8 gtp_loading_fw;

int p_gesture_control = 0;

static int tpd_flag = 0; int tpd_halt = 0; static struct task_struct *thread = NULL; static DECLARE_WAIT_QUEUE_HEAD(waiter);

#ifdef TPD_HAVE_BUTTON static int tpd_keys_local[TPD_KEY_COUNT] = TPD_KEYS; static int tpd_keys_dim_local[TPD_KEY_COUNT][4] = TPD_KEYS_DIM; #endif

#if GTP_GESTURE_WAKEUP typedef enum {     DOZE_DISABLED = 0,     DOZE_ENABLED = 1,     DOZE_WAKEUP = 2, }DOZE_T; static DOZE_T doze_status = DOZE_DISABLED; static s8 gtp_enter_doze(struct i2c_client *client); #endif

#if GTP_COVER_CONTROL static RAW_NOTIFIER_HEAD(cover_chain); #endif

#if GTP_P_GESTURE_CONTROL static RAW_NOTIFIER_HEAD(gesture_chain); #endif

struct device *mx_tsp;   //add by chen for MX gesture

#if GTP_CHARGER_SWITCH     #ifdef MT6573         #define CHR_CON0      (0xF7000000+0x2FA00)     #else         extern kal_bool upmu_is_chr_det(void);     #endif     static void gtp_charger_switch(s32 dir_update); #endif

#if GTP_HAVE_TOUCH_KEY const u16 touch_key_array[] = GTP_KEY_TAB; #define GTP_MAX_KEY_NUM ( sizeof( touch_key_array )/sizeof( touch_key_array[0] ) ) #endif

#if (defined(TPD_WARP_START) && defined(TPD_WARP_END)) static int tpd_wb_start_local[TPD_WARP_CNT] = TPD_WARP_START; static int tpd_wb_end_local[TPD_WARP_CNT]   = TPD_WARP_END; #endif

#if (defined(TPD_HAVE_CALIBRATION) && !defined(TPD_CUSTOM_CALIBRATION)) //static int tpd_calmat_local[8]     = TPD_CALIBRATION_MATRIX; static int tpd_def_calmat_local[8] = TPD_CALIBRATION_MATRIX; #endif

#if GTP_SUPPORT_I2C_DMA s32 i2c_dma_write(struct i2c_client *client, u16 addr, u8 *txbuf, s32 len); s32 i2c_dma_read(struct i2c_client *client, u16 addr, u8 *rxbuf, s32 len);

static u8 *gpDMABuf_va = NULL; static dma_addr_t gpDMABuf_pa = 0; #endif

s32 gtp_send_cfg(struct i2c_client *client);

#if GTP_COVER_CONTROL s32 gtp_send_cfg_cover(struct i2c_client *client); #endif

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

#ifdef CONFIG_OF_TOUCH static irqreturn_t tpd_eint_interrupt_handler(unsigned irq, struct irq_desc *desc); #else static void tpd_eint_interrupt_handler(void); #endif

static int touch_event_handler(void *unused); static int tpd_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id); static int tpd_i2c_detect(struct i2c_client *client, struct i2c_board_info *info); static int tpd_i2c_remove(struct i2c_client *client); s32 gtp_i2c_read_dbl_check(struct i2c_client *client, u16 addr, u8 *rxbuf, int len);

#ifndef MT6572 extern void mt65xx_eint_set_hw_debounce(kal_uint8 eintno, kal_uint32 ms); extern kal_uint32 mt65xx_eint_set_sens(kal_uint8 eintno, kal_bool sens); extern void mt65xx_eint_registration(kal_uint8 eintno, kal_bool Dbounce_En,                                      kal_bool ACT_Polarity, void (EINT_FUNC_PTR)(void),                                      kal_bool auto_umask); #endif

#if GTP_CREATE_WR_NODE extern s32 init_wr_node(struct i2c_client *); extern void uninit_wr_node(void); #endif

#if (GTP_ESD_PROTECT || GTP_COMPATIBLE_MODE) static void force_reset_guitar(void); #endif

#if GTP_ESD_PROTECT static int clk_tick_cnt = 200; static struct delayed_work gtp_esd_check_work; static struct workqueue_struct *gtp_esd_check_workqueue = NULL; static s32 gtp_init_ext_watchdog(struct i2c_client *client); static void gtp_esd_check_func(struct work_struct *); void gtp_esd_switch(struct i2c_client *client, s32 on); u8 esd_running = 0; spinlock_t esd_lock; #endif

#ifdef TPD_PROXIMITY #define TPD_PROXIMITY_VALID_REG                   0x814E #define TPD_PROXIMITY_ENABLE_REG                  0x8042 static u8 tpd_proximity_flag = 0; static u8 tpd_proximity_detect = 1;//0-->close ; 1--> far away #endif

struct i2c_client *i2c_client_point = NULL; static const struct i2c_device_id tpd_i2c_id[] = {{"gt9xx", 0}, {}}; static unsigned short force[] = {0, 0xBA, I2C_CLIENT_END, I2C_CLIENT_END}; static const unsigned short *const forces[] = { force, NULL }; //static struct i2c_client_address_data addr_data = { .forces = forces,}; static struct i2c_board_info __initdata i2c_tpd = { I2C_BOARD_INFO("gt9xx", (0xBA >> 1))}; static struct i2c_driver tpd_i2c_driver = {     .probe = tpd_i2c_probe,     .remove = tpd_i2c_remove,     .detect = tpd_i2c_detect,     .driver.name = "gt9xx",     .id_table = tpd_i2c_id,     .address_list = (const unsigned short *) forces, };

static u8 config[GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH]     = {GTP_REG_CONFIG_DATA >> 8, GTP_REG_CONFIG_DATA & 0xff}; #if GTP_CHARGER_SWITCH static u8 gtp_charger_config[GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH]  = {GTP_REG_CONFIG_DATA >> 8, GTP_REG_CONFIG_DATA & 0xff}; #endif

#pragma pack(1) typedef struct {     u16 pid;                 //product id   //     u16 vid;                 //version id   // } st_tpd_info; #pragma pack()

st_tpd_info tpd_info; u8 int_type = 0; u32 abs_x_max = 0; u32 abs_y_max = 0; u8 gtp_rawdiff_mode = 0; u8 cfg_len = 0; u8 pnl_init_error = 0;

#if GTP_COVER_CONTROL static u8 config_cover[GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH]     = {GTP_REG_CONFIG_DATA >> 8, GTP_REG_CONFIG_DATA & 0xff}; #if GTP_CHARGER_SWITCH static u8 gtp_charger_config_cover[GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH]  = {GTP_REG_CONFIG_DATA >> 8, GTP_REG_CONFIG_DATA & 0xff}; #endif u8 cfg_cover_len = 0; u8 pnl_cover_init_error = 0; #endif

#if GTP_WITH_PEN struct input_dev *pen_dev; #endif

#if GTP_COMPATIBLE_MODE u8 driver_num = 0; u8 sensor_num = 0;

#if GTP_COVER_CONTROL u8 driver_num_cover = 0; u8 sensor_num_cover = 0; #endif

u8 gtp_ref_retries = 0; u8 gtp_clk_retries = 0; CHIP_TYPE_T gtp_chip_type = CHIP_TYPE_GT9; u8 rqst_processing = 0; u8 is_950 = 0;

extern u8 gup_check_fs_mounted(char *path_name); extern u8 gup_clk_calibration(void); extern s32 gup_fw_download_proc(void *dir, u8 dwn_mode); void gtp_get_chip_type(struct i2c_client *client); u8 gtp_fw_startup(struct i2c_client *client); static u8 gtp_bak_ref_proc(struct i2c_client *client, u8 mode); static u8 gtp_main_clk_proc(struct i2c_client *client); static void gtp_recovery_reset(struct i2c_client *client); #endif

/* proc file system */ s32 i2c_read_bytes(struct i2c_client *client, u16 addr, u8 *rxbuf, int len); s32 i2c_write_bytes(struct i2c_client *client, u16 addr, u8 *txbuf, int len);

static ssize_t gt91xx_config_read_proc(struct file *, char __user *, size_t, loff_t *); static ssize_t gt91xx_config_write_proc(struct file *, const char __user *, size_t, loff_t *);

static struct proc_dir_entry *gt91xx_config_proc = NULL; static const struct file_operations config_proc_ops = {     .owner = THIS_MODULE,     .read = gt91xx_config_read_proc,     .write = gt91xx_config_write_proc, };

#define VELOCITY_CUSTOM #ifdef VELOCITY_CUSTOM #include <linux/device.h> #include <linux/miscdevice.h> #include <asm/uaccess.h>

#ifndef TPD_VELOCITY_CUSTOM_X #define TPD_VELOCITY_CUSTOM_X 10 #endif #ifndef TPD_VELOCITY_CUSTOM_Y #define TPD_VELOCITY_CUSTOM_Y 10 #endif

// for magnify velocity******************************************** #define TOUCH_IOC_MAGIC 'A'

#define TPD_GET_VELOCITY_CUSTOM_X _IO(TOUCH_IOC_MAGIC,0) #define TPD_GET_VELOCITY_CUSTOM_Y _IO(TOUCH_IOC_MAGIC,1)

int g_v_magnify_x = TPD_VELOCITY_CUSTOM_X; int g_v_magnify_y = TPD_VELOCITY_CUSTOM_Y;

#if GTP_COVER_CONTROL int register_cover_notifier(struct notifier_block *nb) {   return raw_notifier_chain_register(&cover_chain, nb); }

int unregister_cover_notifier(struct notifier_block *nb) {   return raw_notifier_chain_unregister(&cover_chain,nb); }

int cover_notifier_call_chain(unsigned long val, void *v) {   return raw_notifier_call_chain(&cover_chain, val, v); } EXPORT_SYMBOL(cover_notifier_call_chain);

static int cover_event(struct notifier_block *this, unsigned long event, void *ptr) {   GTP_DEBUG("cover_event event=%ld\n",event);   if(event==0)   {    gtp_send_cfg(i2c_client_point);   }   else   {    gtp_send_cfg_cover(i2c_client_point);   }   return 0; }

static struct notifier_block cover_notifier1 = {    .notifier_call = cover_event, }; #endif

#if GTP_P_GESTURE_CONTROL int register_gesture_notifier(struct notifier_block *nb) {   return raw_notifier_chain_register(&gesture_chain, nb); }

int unregister_gesture_notifier(struct notifier_block *nb) {   return raw_notifier_chain_unregister(&gesture_chain,nb); }

int gesture_notifier_call_chain(unsigned long val, void *v) {   return raw_notifier_call_chain(&gesture_chain, val, v); } EXPORT_SYMBOL(gesture_notifier_call_chain);

static int gesture_event(struct notifier_block *this, unsigned long event, void *ptr) {   GTP_DEBUG("gesture_event event=%ld\n",event);   if(event==0)   {    p_gesture_control = 0;   }   else   {    p_gesture_control = 1;   }   return 0; }

static struct notifier_block gesture_notifier1 = {    .notifier_call = gesture_event, }; #endif

 

//add by chen for MX gesture u8 gesture_three_byte_one = 0; u8 gesture_three_byte_two = 0; u8 gesture_three_byte_three = 0; u8 gesture_three_byte_four = 0; int gesture_data=0; static ssize_t gesture_data_store(struct device* dev, struct device_attribute *attr,                                   const char *buf, size_t count) {  /*  struct alsps_context *cxt = NULL;  //int err =0;  ALSPS_LOG("als_store_active buf=%s\n",buf);  mutex_lock(&alsps_context_obj->alsps_op_mutex);  cxt = alsps_context_obj;

    if (!strncmp(buf, "1", 1))  {        als_enable_data(1);      }  else if (!strncmp(buf, "0", 1))  {        als_enable_data(0);      }  else  {    ALSPS_ERR(" alsps_store_active error !!\n");  }  mutex_unlock(&alsps_context_obj->alsps_op_mutex);  ALSPS_LOG(" alsps_store_active done\n");     return count;  */     return 0; } /*----------------------------------------------------------------------------*/ static ssize_t gesture_data_show(struct device* dev,                                  struct device_attribute *attr, char *buf) { /*  struct alsps_context *cxt = NULL;  int div = 0;  cxt = alsps_context_obj;  div=cxt->als_data.vender_div;  ALSPS_LOG("als vender_div value: %d\n", div);  return snprintf(buf, PAGE_SIZE, "%d\n", div); */  GTP_DEBUG("gesture_data_show gesture_data=%x\n",gesture_data);  return snprintf(buf, PAGE_SIZE, "%d\n", gesture_data); }

static ssize_t gesture_control_node_store(struct device* dev, struct device_attribute *attr,                                   const char *buf, size_t count) {      u32 value,value1,value2;     sscanf(buf, "%x", &value);     value1 = value&0x000000ff;     value2 = (value>>16)&0x000000ff;     if(value2 == 1)     {      gesture_three_byte_one = value1;     }     else if(value2 == 2)     {      gesture_three_byte_two = value1;     }     else if(value2 == 3)     {      gesture_three_byte_three = value1;     }     else if(value2 == 4)     {      gesture_three_byte_four = value1;     }     GTP_DEBUG("gesture_three_byte_one=%x,gesture_three_byte_two=%x,gesture_three_byte_three=%x,gesture_three_byte_four=%x\n",gesture_three_byte_one,gesture_three_byte_two,gesture_three_byte_three,gesture_three_byte_four);     return count; } /*----------------------------------------------------------------------------*/ static ssize_t gesture_control_node_show(struct device* dev,                                  struct device_attribute *attr, char *buf) {  return 0; }

static ssize_t gesture_control_store(struct device* dev, struct device_attribute *attr,                                   const char *buf, size_t count) {      if(buf[2] == 1)     {      gesture_three_byte_one = buf[0];     }     else if(buf[2] == 2)     {      gesture_three_byte_two = buf[0];     }     else if(buf[2] == 3)     {      gesture_three_byte_three = buf[0];     }     else if(buf[2] == 4)     {      gesture_three_byte_four = buf[0];     }     GTP_DEBUG("gesture_three_byte_one=%x,gesture_three_byte_two=%x,gesture_three_byte_three=%x,gesture_three_byte_four=%x\n",gesture_three_byte_one,gesture_three_byte_two,gesture_three_byte_three,gesture_three_byte_four);     return count; } /*----------------------------------------------------------------------------*/ static ssize_t gesture_control_show(struct device* dev,                                  struct device_attribute *attr, char *buf) {  return 0; }

 

static ssize_t cover_control_store(struct device* dev, struct device_attribute *attr,                                   const char *buf, size_t count) {   u32 value = 0;  u8 buf_value = buf[0];      sscanf(buf, "%d", &value);  GTP_DEBUG("cover_control_store buf_value=%d,value=%d\n",buf_value,value);  if(value==0)        {        gtp_send_cfg(i2c_client_point);        }       else       {       gtp_send_cfg_cover(i2c_client_point);       }      return 0; } /*----------------------------------------------------------------------------*/ static ssize_t cover_control_show(struct device* dev,                                  struct device_attribute *attr, char *buf) {  return 0; }

DEVICE_ATTR(gesture_data,       S_IWUSR | S_IRUGO, gesture_data_show, gesture_data_store); DEVICE_ATTR(gesture_control_node,        S_IWUSR | S_IRUGO, gesture_control_node_show,  gesture_control_node_store); DEVICE_ATTR(cover_control,        S_IWUSR | S_IRUGO, cover_control_show,  cover_control_store); DEVICE_ATTR(gesture_control,        S_IWUSR | S_IRUGO, gesture_control_show,  gesture_control_store);

static struct attribute *gesture_attributes[] = {  &dev_attr_gesture_data.attr,  &dev_attr_gesture_control_node.attr,  &dev_attr_gesture_control.attr,  &dev_attr_cover_control.attr,  NULL };

static struct attribute_group gesture_attribute_group = {  .attrs = gesture_attributes }; //add end

static int tpd_misc_open(struct inode *inode, struct file *file) {     return nonseekable_open(inode, file); }

static int tpd_misc_release(struct inode *inode, struct file *file) {     return 0; }

static long tpd_unlocked_ioctl(struct file *file, unsigned int cmd,                                unsigned long arg) {     //char strbuf[256];     void __user *data;

    long err = 0;

    if (_IOC_DIR(cmd) & _IOC_READ)     {         err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd));     }     else if (_IOC_DIR(cmd) & _IOC_WRITE)     {         err = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd));     }

    if (err)     {         printk("tpd: access error: %08X, (%2d, %2d)\n", cmd, _IOC_DIR(cmd), _IOC_SIZE(cmd));         return -EFAULT;     }

    switch (cmd)     {         case TPD_GET_VELOCITY_CUSTOM_X:             data = (void __user *) arg;

            if (data == NULL)             {                 err = -EINVAL;                 break;             }

            if (copy_to_user(data, &g_v_magnify_x, sizeof(g_v_magnify_x)))             {                 err = -EFAULT;                 break;             }

            break;

        case TPD_GET_VELOCITY_CUSTOM_Y:             data = (void __user *) arg;

            if (data == NULL)             {                 err = -EINVAL;                 break;             }

            if (copy_to_user(data, &g_v_magnify_y, sizeof(g_v_magnify_y)))             {                 err = -EFAULT;                 break;             }

            break;

        default:             printk("tpd: unknown IOCTL: 0x%08x\n", cmd);             err = -ENOIOCTLCMD;             break;

    }

    return err; }

static struct file_operations tpd_fops = { //  .owner = THIS_MODULE,     .open = tpd_misc_open,     .release = tpd_misc_release,     .unlocked_ioctl = tpd_unlocked_ioctl, }; /*----------------------------------------------------------------------------*/ static struct miscdevice tpd_misc_device = {     .minor = MISC_DYNAMIC_MINOR,     .name = "touch",     .fops = &tpd_fops, };

//********************************************** #endif

static int tpd_i2c_detect(struct i2c_client *client, struct i2c_board_info *info) {     strcpy(info->type, "mtk-tpd");     return 0; }

#ifdef TPD_PROXIMITY static s32 tpd_get_ps_value(void) {     return tpd_proximity_detect; }

static s32 tpd_enable_ps(s32 enable) {     u8  state;     s32 ret = -1;

    if (enable)     {         state = 1;         tpd_proximity_flag = 1;         GTP_INFO("TPD proximity function to be on.");     }     else     {         state = 0;         tpd_proximity_flag = 0;         GTP_INFO("TPD proximity function to be off.");     }

    ret = i2c_write_bytes(i2c_client_point, TPD_PROXIMITY_ENABLE_REG, &state, 1);

    if (ret < 0)     {         GTP_ERROR("TPD %s proximity cmd failed.", state ? "enable" : "disable");         return ret;     }

    GTP_INFO("TPD proximity function %s success.", state ? "enable" : "disable");     return 0; }

s32 tpd_ps_operate(void *self, u32 command, void *buff_in, s32 size_in,                    void *buff_out, s32 size_out, s32 *actualout) {     s32 err = 0;     s32 value;     hwm_sensor_data *sensor_data;

    switch (command)     {         case SENSOR_DELAY:             if ((buff_in == NULL) || (size_in < sizeof(int)))             {                 GTP_ERROR("Set delay parameter error!");                 err = -EINVAL;             }

            // Do nothing             break;

        case SENSOR_ENABLE:             if ((buff_in == NULL) || (size_in < sizeof(int)))             {                 GTP_ERROR("Enable sensor parameter error!");                 err = -EINVAL;             }             else             {                 value = *(int *)buff_in;                 err = tpd_enable_ps(value);             }

            break;

        case SENSOR_GET_DATA:             if ((buff_out == NULL) || (size_out < sizeof(hwm_sensor_data)))             {                 GTP_ERROR("Get sensor data parameter error!");                 err = -EINVAL;             }             else             {                 sensor_data = (hwm_sensor_data *)buff_out;                 sensor_data->values[0] = tpd_get_ps_value();                 sensor_data->value_divide = 1;                 sensor_data->status = SENSOR_STATUS_ACCURACY_MEDIUM;             }

            break;

        default:             GTP_ERROR("proxmy sensor operate function no this parameter %d!\n", command);             err = -1;             break;     }

    return err; } #endif

static ssize_t gt91xx_config_read_proc(struct file *file, char __user *page, size_t size, loff_t *ppos) {     char *ptr = page;     char temp_data[GTP_CONFIG_MAX_LENGTH + 2] = {0};     int i;         if (*ppos)  // CMD call again     {         return 0;     }         ptr += sprintf(ptr, "==== GT9XX config init value====\n");

    for (i = 0 ; i < GTP_CONFIG_MAX_LENGTH ; i++)     {         ptr += sprintf(ptr, "0x%02X ", config[i + 2]);

        if (i % 8 == 7)             ptr += sprintf(ptr, "\n");     }

    ptr += sprintf(ptr, "\n");

    ptr += sprintf(ptr, "==== GT9XX config real value====\n");     i2c_read_bytes(i2c_client_point, GTP_REG_CONFIG_DATA, temp_data, GTP_CONFIG_MAX_LENGTH);

    for (i = 0 ; i < GTP_CONFIG_MAX_LENGTH ; i++)     {         ptr += sprintf(ptr, "0x%02X ", temp_data[i]);

        if (i % 8 == 7)             ptr += sprintf(ptr, "\n");     }     *ppos += ptr - page;     return (ptr - page); }

static ssize_t gt91xx_config_write_proc(struct file *filp, const char __user *buffer, size_t count, loff_t *off) {     s32 ret = 0;

    GTP_DEBUG("write count %zd\n", count);

    if (count > GTP_CONFIG_MAX_LENGTH)     {         GTP_ERROR("size not match [%d:%zd]\n", GTP_CONFIG_MAX_LENGTH, count);         return -EFAULT;     }

    if (copy_from_user(&config[2], buffer, count))     {         GTP_ERROR("copy from user fail\n");         return -EFAULT;     }

    ret = gtp_send_cfg(i2c_client_point);     abs_x_max = (config[RESOLUTION_LOC + 1] << 8) + config[RESOLUTION_LOC];     abs_y_max = (config[RESOLUTION_LOC + 3] << 8) + config[RESOLUTION_LOC + 2];     int_type = (config[TRIGGER_LOC]) & 0x03;

    if (ret < 0)     {         GTP_ERROR("send config failed.");     }

    return count; }

#if GTP_SUPPORT_I2C_DMA s32 i2c_dma_read(struct i2c_client *client, u16 addr, u8 *rxbuf, s32 len) {     int ret;     s32 retry = 0;     u8 buffer[2];

    struct i2c_msg msg[2] =     {         {             .addr = (client->addr & I2C_MASK_FLAG),             .flags = 0,             .buf = buffer,             .len = 2,             .timing = I2C_MASTER_CLOCK         },         {             .addr = (client->addr & I2C_MASK_FLAG),             .ext_flag = (client->ext_flag | I2C_ENEXT_FLAG | I2C_DMA_FLAG),             .flags = I2C_M_RD,             .buf = (u8*)gpDMABuf_pa,                 .len = len,             .timing = I2C_MASTER_CLOCK         },     };         buffer[0] = (addr >> 8) & 0xFF;     buffer[1] = addr & 0xFF;

    if (rxbuf == NULL)         return -1;

    //GTP_DEBUG("dma i2c read: 0x%04X, %d bytes(s)", addr, len);     for (retry = 0; retry < 5; ++retry)     {         ret = i2c_transfer(client->adapter, &msg[0], 2);         if (ret < 0)         {             continue;         }         memcpy(rxbuf, gpDMABuf_va, len);         return 0;     }     GTP_ERROR("Dma I2C Read Error: 0x%04X, %d byte(s), err-code: %d", addr, len, ret);     return ret; }

s32 i2c_dma_write(struct i2c_client *client, u16 addr, u8 *txbuf, s32 len) {     int ret;     s32 retry = 0;     u8 *wr_buf = gpDMABuf_va;         struct i2c_msg msg =     {         .addr = (client->addr & I2C_MASK_FLAG),         .ext_flag = (client->ext_flag | I2C_ENEXT_FLAG | I2C_DMA_FLAG),         .flags = 0,         .buf = (u8*)gpDMABuf_pa,         .len = 2 + len,         .timing = I2C_MASTER_CLOCK     };         wr_buf[0] = (u8)((addr >> 8) & 0xFF);     wr_buf[1] = (u8)(addr & 0xFF);

    if (txbuf == NULL)         return -1;         //GTP_DEBUG("dma i2c write: 0x%04X, %d bytes(s)", addr, len);     memcpy(wr_buf+2, txbuf, len);     for (retry = 0; retry < 5; ++retry)     {         ret = i2c_transfer(client->adapter, &msg, 1);         if (ret < 0)         {             continue;         }         return 0;     }     GTP_ERROR("Dma I2C Write Error: 0x%04X, %d byte(s), err-code: %d", addr, len, ret);     return ret; }

s32 i2c_read_bytes_dma(struct i2c_client *client, u16 addr, u8 *rxbuf, s32 len) {     s32 left = len;     s32 read_len = 0;     u8 *rd_buf = rxbuf;     s32 ret = 0;            //GTP_DEBUG("Read bytes dma: 0x%04X, %d byte(s)", addr, len);     while (left > 0)     {         if (left > GTP_DMA_MAX_TRANSACTION_LENGTH)         {             read_len = GTP_DMA_MAX_TRANSACTION_LENGTH;         }         else         {             read_len = left;         }         ret = i2c_dma_read(client, addr, rd_buf, read_len);         if (ret < 0)         {             GTP_ERROR("dma read failed");             return -1;         }                 left -= read_len;         addr += read_len;         rd_buf += read_len;     }     return 0; }

s32 i2c_write_bytes_dma(struct i2c_client *client, u16 addr, u8 *txbuf, s32 len) {

    s32 ret = 0;     s32 write_len = 0;     s32 left = len;     u8 *wr_buf = txbuf;         //GTP_DEBUG("Write bytes dma: 0x%04X, %d byte(s)", addr, len);     while (left > 0)     {         if (left > GTP_DMA_MAX_I2C_TRANSFER_SIZE)         {             write_len = GTP_DMA_MAX_I2C_TRANSFER_SIZE;         }         else         {             write_len = left;         }         ret = i2c_dma_write(client, addr, wr_buf, write_len);                 if (ret < 0)         {             GTP_ERROR("dma i2c write failed!");             return -1;         }                 left -= write_len;         addr += write_len;         wr_buf += write_len;     }     return 0; } #endif

int i2c_read_bytes_non_dma(struct i2c_client *client, u16 addr, u8 *rxbuf, int len) {     u8 buffer[GTP_ADDR_LENGTH];     u8 retry;     u16 left = len;     u16 offset = 0;

    struct i2c_msg msg[2] =     {         {             .addr = ((client->addr &I2C_MASK_FLAG) | (I2C_ENEXT_FLAG)),             //.addr = ((client->addr &I2C_MASK_FLAG) | (I2C_PUSHPULL_FLAG)),             .flags = 0,             .buf = buffer,             .len = GTP_ADDR_LENGTH,             .timing = I2C_MASTER_CLOCK         },         {             .addr = ((client->addr &I2C_MASK_FLAG) | (I2C_ENEXT_FLAG)),             //.addr = ((client->addr &I2C_MASK_FLAG) | (I2C_PUSHPULL_FLAG)),             .flags = I2C_M_RD,             .timing = I2C_MASTER_CLOCK         },     };

    if (rxbuf == NULL)         return -1;

    //GTP_DEBUG("i2c_read_bytes to device %02X address %04X len %d\n", client->addr, addr, len);

    while (left > 0)     {         buffer[0] = ((addr + offset) >> 8) & 0xFF;         buffer[1] = (addr + offset) & 0xFF;

        msg[1].buf = &rxbuf[offset];

        if (left > MAX_TRANSACTION_LENGTH)         {             msg[1].len = MAX_TRANSACTION_LENGTH;             left -= MAX_TRANSACTION_LENGTH;             offset += MAX_TRANSACTION_LENGTH;         }         else         {             msg[1].len = left;             left = 0;         }

        retry = 0;

        while (i2c_transfer(client->adapter, &msg[0], 2) != 2)         {             retry++;

            //if (retry == 20)             if (retry == 5)             {                 GTP_ERROR("I2C read 0x%X length=%d failed\n", addr + offset, len);                 return -1;             }         }     }

    return 0; }

int i2c_read_bytes(struct i2c_client *client, u16 addr, u8 *rxbuf, int len) { #if GTP_SUPPORT_I2C_DMA     return i2c_read_bytes_dma(client, addr, rxbuf, len); #else     return i2c_read_bytes_non_dma(client, addr, rxbuf, len); #endif }

s32 gtp_i2c_read(struct i2c_client *client, u8 *buf, s32 len) {     s32 ret = -1;     u16 addr = (buf[0] << 8) + buf[1];

    ret = i2c_read_bytes_non_dma(client, addr, &buf[2], len - 2);

    if (!ret)     {         return 2;     }     else     {     #if GTP_GESTURE_WAKEUP         if (DOZE_ENABLED == doze_status)         {             return ret;         }     #endif     #if GTP_COMPATIBLE_MODE         if (CHIP_TYPE_GT9F == gtp_chip_type)         {             gtp_recovery_reset(client);         }         else     #endif         {             gtp_reset_guitar(client, 20);         }         return ret;     } }

s32 gtp_i2c_read_dbl_check(struct i2c_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; }

int i2c_write_bytes_non_dma(struct i2c_client *client, u16 addr, u8 *txbuf, int len) {     u8 buffer[MAX_TRANSACTION_LENGTH];     u16 left = len;     u16 offset = 0;     u8 retry = 0;

    struct i2c_msg msg =     {         .addr = ((client->addr &I2C_MASK_FLAG) | (I2C_ENEXT_FLAG)),         //.addr = ((client->addr &I2C_MASK_FLAG) | (I2C_PUSHPULL_FLAG)),         .flags = 0,         .buf = buffer,         .timing = I2C_MASTER_CLOCK,     };

    if (txbuf == NULL)         return -1;

    //GTP_DEBUG("i2c_write_bytes to device %02X address %04X len %d\n", client->addr, addr, len);

    while (left > 0)     {         retry = 0;

        buffer[0] = ((addr + offset) >> 8) & 0xFF;         buffer[1] = (addr + offset) & 0xFF;

        if (left > MAX_I2C_TRANSFER_SIZE)         {             memcpy(&buffer[GTP_ADDR_LENGTH], &txbuf[offset], MAX_I2C_TRANSFER_SIZE);             msg.len = MAX_TRANSACTION_LENGTH;             left -= MAX_I2C_TRANSFER_SIZE;             offset += MAX_I2C_TRANSFER_SIZE;         }         else         {             memcpy(&buffer[GTP_ADDR_LENGTH], &txbuf[offset], left);             msg.len = left + GTP_ADDR_LENGTH;             left = 0;         }

        //GTP_DEBUG("byte left %d offset %d\n", left, offset);

        while (i2c_transfer(client->adapter, &msg, 1) != 1)         {             retry++;

            //if (retry == 20)             if (retry == 5)             {                 GTP_ERROR("I2C write 0x%X%X length=%d failed\n", buffer[0], buffer[1], len);                 return -1;             }         }     }

    return 0; }

int i2c_write_bytes(struct i2c_client *client, u16 addr, u8 *txbuf, int len) { #if GTP_SUPPORT_I2C_DMA     return i2c_write_bytes_dma(client, addr, txbuf, len); #else     return i2c_write_bytes_non_dma(client, addr, txbuf, len); #endif }

s32 gtp_i2c_write(struct i2c_client *client, u8 *buf, s32 len) {     s32 ret = -1;     u16 addr = (buf[0] << 8) + buf[1];

    ret = i2c_write_bytes_non_dma(client, addr, &buf[2], len - 2);

    if (!ret)     {         return 1;     }     else     {     #if GTP_GESTURE_WAKEUP         if (DOZE_ENABLED == doze_status)         {             return ret;         }     #endif     #if GTP_COMPATIBLE_MODE         if (CHIP_TYPE_GT9F == gtp_chip_type)         {             gtp_recovery_reset(client);         }         else     #endif         {             gtp_reset_guitar(client, 20);         }         return ret;     } }

 

/******************************************************* Function:     Send config Function.

Input:     client: i2c client.

Output:     Executive outcomes.0--success,non-0--fail. *******************************************************/ s32 gtp_send_cfg(struct i2c_client *client) {     s32 ret = 1;

#if GTP_DRIVER_SEND_CFG     s32 retry = 0;

 if (pnl_init_error)     {         GTP_INFO("Error occurred in init_panel, no config sent!");         return 0;     }         GTP_INFO("Driver Send Config");     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; } #if GTP_CHARGER_SWITCH static int gtp_send_chr_cfg(struct i2c_client *client) {  s32 ret = 1; #if GTP_DRIVER_SEND_CFG     s32 retry = 0;

 if (pnl_init_error) {         GTP_INFO("Error occurred in init_panel, no config sent!");         return 0;     }         GTP_INFO("Driver Send Config");     for (retry = 0; retry < 5; retry++) {         ret = gtp_i2c_write(client, gtp_charger_config, GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH);         if (ret > 0) {             break;         }     } #endif   return ret; } #endif

/******************************************************* Function:     Send config Function.

Input:     client: i2c client.

Output:     Executive outcomes.0--success,non-0--fail. *******************************************************/ #if GTP_COVER_CONTROL s32 gtp_send_cfg_cover(struct i2c_client *client) {     s32 ret = 1;

#if GTP_DRIVER_SEND_CFG     s32 retry = 0;

 if (pnl_cover_init_error)     {         GTP_INFO("Error occurred in init_panel, no config sent!");         return 0;     }         GTP_INFO("Driver Send Config");     for (retry = 0; retry < 5; retry++)     {         ret = gtp_i2c_write(client, config_cover, GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH);

        if (ret > 0)         {             break;         }     } #endif     return ret; } #endif /******************************************************* Function:     Read goodix touchscreen version function.

Input:     client: i2c client struct.     version:address to store version info

Output:     Executive outcomes.0---succeed. *******************************************************/ s32 gtp_read_version(struct i2c_client *client, u16 *version) {     s32 ret = -1;     s32 i;     u8 buf[8] = {GTP_REG_VERSION >> 8, GTP_REG_VERSION & 0xff};

    GTP_DEBUG_FUNC();

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

    if (ret < 0)     {         GTP_ERROR("GTP read version failed");         return ret;     }

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

    tpd_info.vid = *version;     tpd_info.pid = 0x00;

    for (i = 0; i < 4; i++)     {         if (buf[i + 2] < 0x30)break;

        tpd_info.pid |= ((buf[i + 2] - 0x30) << ((3 - i) * 4));     }

    if (buf[5] == 0x00)     {                GTP_INFO("IC VERSION: %c%c%c_%02x%02x",              buf[2], buf[3], buf[4], buf[7], buf[6]);      }     else     {         GTP_INFO("IC VERSION:%c%c%c%c_%02x%02x",              buf[2], buf[3], buf[4], buf[5], buf[7], buf[6]);     }     return ret; }

/******************************************************* Function:     GTP initialize function.

Input:     client: i2c client private struct.

Output:     Executive outcomes.0---succeed. *******************************************************/ static s32 gtp_init_panel(struct i2c_client *client) {     s32 ret = 0;     char *info = tp_info;

#if GTP_DRIVER_SEND_CFG     s32 i;     u8 check_sum = 0;     u8 opr_buf[16];     u8 sensor_id = 0;   u8 drv_cfg_version;   u8 flash_cfg_version;

    u8 cfg_info_group0[] = CTP_CFG_GROUP0;     u8 cfg_info_group1[] = CTP_CFG_GROUP1;     u8 cfg_info_group2[] = CTP_CFG_GROUP2;     u8 cfg_info_group3[] = CTP_CFG_GROUP3;     u8 cfg_info_group4[] = CTP_CFG_GROUP4;     u8 cfg_info_group5[] = CTP_CFG_GROUP5;     u8 *send_cfg_buf[] = {cfg_info_group0, cfg_info_group1, cfg_info_group2,                         cfg_info_group3, cfg_info_group4, cfg_info_group5};     u8 cfg_info_len[] = { CFG_GROUP_LEN(cfg_info_group0),                           CFG_GROUP_LEN(cfg_info_group1),                           CFG_GROUP_LEN(cfg_info_group2),                           CFG_GROUP_LEN(cfg_info_group3),                           CFG_GROUP_LEN(cfg_info_group4),                           CFG_GROUP_LEN(cfg_info_group5)}; #if GTP_CHARGER_SWITCH  const u8 cfg_grp0_charger[] = GTP_CFG_GROUP0_CHARGER;  const u8 cfg_grp1_charger[] = GTP_CFG_GROUP1_CHARGER;  const u8 cfg_grp2_charger[] = GTP_CFG_GROUP2_CHARGER;  const u8 cfg_grp3_charger[] = GTP_CFG_GROUP3_CHARGER;  const u8 cfg_grp4_charger[] = GTP_CFG_GROUP4_CHARGER;  const u8 cfg_grp5_charger[] = GTP_CFG_GROUP5_CHARGER;  const u8 *cfgs_charger[] = {   cfg_grp0_charger, cfg_grp1_charger, cfg_grp2_charger,   cfg_grp3_charger, cfg_grp4_charger, cfg_grp5_charger  };  u8 cfg_lens_charger[] = {       CFG_GROUP_LEN(cfg_grp0_charger),       CFG_GROUP_LEN(cfg_grp1_charger),       CFG_GROUP_LEN(cfg_grp2_charger),       CFG_GROUP_LEN(cfg_grp3_charger),       CFG_GROUP_LEN(cfg_grp4_charger),       CFG_GROUP_LEN(cfg_grp5_charger)}; #endif

    GTP_DEBUG("Config Groups\' Lengths: %d, %d, %d, %d, %d, %d",         cfg_info_len[0], cfg_info_len[1], cfg_info_len[2], cfg_info_len[3],         cfg_info_len[4], cfg_info_len[5]);

    if ((!cfg_info_len[1]) && (!cfg_info_len[2]) &&         (!cfg_info_len[3]) && (!cfg_info_len[4]) &&         (!cfg_info_len[5]))     {         sensor_id = 0;     }     else     {     #if GTP_COMPATIBLE_MODE         if (CHIP_TYPE_GT9F == gtp_chip_type)         {             msleep(50);         }     #endif         ret = gtp_i2c_read_dbl_check(client, GTP_REG_SENSOR_ID, &sensor_id, 1);         if (SUCCESS == ret)         {             if (sensor_id >= 0x06)             {                 GTP_ERROR("Invalid sensor_id(0x%02X), No Config Sent!", sensor_id);                 pnl_init_error = 1;                 return -1;             }         }         else         {             GTP_ERROR("Failed to get sensor_id, No config sent!");             pnl_init_error = 1;             return -1;         }         GTP_INFO("Sensor_ID: %d", sensor_id);   if(sensor_id==2)   {    info += sprintf(info,"GT915L,");   info += sprintf(info,"O-film,");    info += sprintf(info, "%04x", tpd_info.vid);   }   else if(sensor_id==3)   {    info += sprintf(info,"GT915L,");   info += sprintf(info,"Yassy,");    info += sprintf(info, "%04x", tpd_info.vid);   }     }         cfg_len = cfg_info_len[sensor_id];         GTP_INFO("CTP_CONFIG_GROUP%d used, config length: %d", sensor_id, cfg_len);         if (cfg_len < GTP_CONFIG_MIN_LENGTH)     {         GTP_ERROR("CTP_CONFIG_GROUP%d is INVALID CONFIG GROUP! NO Config Sent! You need to check you header file CFG_GROUP section!", sensor_id);         pnl_init_error = 1;         return -1;     }     #if GTP_COMPATIBLE_MODE     if (CHIP_TYPE_GT9F != gtp_chip_type) #endif  {      ret = gtp_i2c_read_dbl_check(client, GTP_REG_CONFIG_DATA, &opr_buf[0], 1);         if (ret == SUCCESS)      {          GTP_DEBUG("CFG_CONFIG_GROUP%d Config Version: %d, 0x%02X; IC Config Version: %d, 0x%02X", sensor_id,                      send_cfg_buf[sensor_id][0], send_cfg_buf[sensor_id][0], opr_buf[0], opr_buf[0]);      flash_cfg_version = opr_buf[0];    drv_cfg_version = send_cfg_buf[sensor_id][0];       // backup  config version              if (flash_cfg_version < 90 && flash_cfg_version > drv_cfg_version) {              send_cfg_buf[sensor_id][0] = 0x00;          }      }      else      {          GTP_ERROR("Failed to get ic config version!No config sent!");          return -1;      }  }      memset(&config[GTP_ADDR_LENGTH], 0, GTP_CONFIG_MAX_LENGTH);     memcpy(&config[GTP_ADDR_LENGTH], send_cfg_buf[sensor_id], cfg_len);

#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);         if (GTP_INT_TRIGGER == 0)  //RISING     {         config[TRIGGER_LOC] &= 0xfe;     }     else if (GTP_INT_TRIGGER == 1)  //FALLING     {         config[TRIGGER_LOC] |= 0x01;     } #endif  // GTP_CUSTOM_CFG

 check_sum = 0;  for (i = GTP_ADDR_LENGTH; i < cfg_len; i++)  {   check_sum += config[i];  }  config[cfg_len] = (~check_sum) + 1;

#if GTP_CHARGER_SWITCH  GTP_DEBUG("Charger Config Groups Length: %d, %d, %d, %d, %d, %d", cfg_lens_charger[0],     cfg_lens_charger[1], cfg_lens_charger[2], cfg_lens_charger[3], cfg_lens_charger[4], cfg_lens_charger[5]);

 memset(&gtp_charger_config[GTP_ADDR_LENGTH], 0, GTP_CONFIG_MAX_LENGTH);  if (cfg_lens_charger[sensor_id] == cfg_len)   memcpy(&gtp_charger_config[GTP_ADDR_LENGTH], cfgs_charger[sensor_id], cfg_len);

#if GTP_CUSTOM_CFG  gtp_charger_config[RESOLUTION_LOC] = (u8) GTP_MAX_WIDTH;  gtp_charger_config[RESOLUTION_LOC + 1] = (u8) (GTP_MAX_WIDTH >> 8);  gtp_charger_config[RESOLUTION_LOC + 2] = (u8) GTP_MAX_HEIGHT;  gtp_charger_config[RESOLUTION_LOC + 3] = (u8) (GTP_MAX_HEIGHT >> 8);

 if (GTP_INT_TRIGGER == 0)  /* RISING  */   gtp_charger_config[TRIGGER_LOC] &= 0xfe;  else if (GTP_INT_TRIGGER == 1) /* FALLING */   gtp_charger_config[TRIGGER_LOC] |= 0x01; #endif /* END GTP_CUSTOM_CFG */  if (cfg_lens_charger[sensor_id] != cfg_len)   memset(&gtp_charger_config[GTP_ADDR_LENGTH], 0, GTP_CONFIG_MAX_LENGTH);     check_sum = 0;  for (i = GTP_ADDR_LENGTH; i < cfg_len; i++)  {   check_sum += gtp_charger_config[i];  }  gtp_charger_config[cfg_len] = (~check_sum) + 1;

#endif /* END GTP_CHARGER_SWITCH */      #else // DRIVER NOT SEND CONFIG     cfg_len = GTP_CONFIG_MAX_LENGTH;     ret = gtp_i2c_read(client, config, cfg_len + GTP_ADDR_LENGTH);     if (ret < 0)     {         GTP_ERROR("Read Config Failed, Using DEFAULT Resolution & INT Trigger!");         abs_x_max = GTP_MAX_WIDTH;         abs_y_max = GTP_MAX_HEIGHT;         int_type = GTP_INT_TRIGGER;     } #endif // GTP_DRIVER_SEND_CFG

    GTP_DEBUG_FUNC();     if ((abs_x_max == 0) && (abs_y_max == 0))     {         abs_x_max = (config[RESOLUTION_LOC + 1] << 8) + config[RESOLUTION_LOC];         abs_y_max = (config[RESOLUTION_LOC + 3] << 8) + config[RESOLUTION_LOC + 2];         int_type = (config[TRIGGER_LOC]) & 0x03;     }     #if GTP_COMPATIBLE_MODE     if (CHIP_TYPE_GT9F == gtp_chip_type)     {         u8 have_key = 0;         if (is_950)         {             driver_num = config[GTP_REG_MATRIX_DRVNUM - GTP_REG_CONFIG_DATA + 2];             sensor_num = config[GTP_REG_MATRIX_SENNUM - GTP_REG_CONFIG_DATA + 2];         }         else         {             driver_num = (config[CFG_LOC_DRVA_NUM]&0x1F) + (config[CFG_LOC_DRVB_NUM]&0x1F);             sensor_num = (config[CFG_LOC_SENS_NUM]&0x0F) + ((config[CFG_LOC_SENS_NUM]>>4)&0x0F);         }                 have_key = config[GTP_REG_HAVE_KEY - GTP_REG_CONFIG_DATA + 2] & 0x01;  // have key or not         if (1 == have_key)         {             driver_num--;         }                 GTP_INFO("Driver * Sensor: %d * %d(Key: %d), X_MAX = %d, Y_MAX = %d, TRIGGER = 0x%02x",             driver_num, sensor_num, have_key, abs_x_max,abs_y_max,int_type);     }     else #endif     { #if GTP_DRIVER_SEND_CFG         ret = gtp_send_cfg(client);         if (ret < 0)         {             GTP_ERROR("Send config error.");         } #if GTP_COMPATIBLE_MODE      if (CHIP_TYPE_GT9F != gtp_chip_type) #endif    {         /* for resume to send config */   if (flash_cfg_version < 90 && flash_cfg_version > drv_cfg_version) {            config[GTP_ADDR_LENGTH] = drv_cfg_version;          check_sum = 0;          for (i = GTP_ADDR_LENGTH; i < cfg_len; i++)          {              check_sum += config[i];          }          config[cfg_len] = (~check_sum) + 1;   }    } #endif         GTP_INFO("X_MAX = %d, Y_MAX = %d, TRIGGER = 0x%02x",             abs_x_max,abs_y_max,int_type);     }         msleep(10);     return 0; }

/******************************************************* Function:     GTP initialize function.

Input:     client: i2c client private struct.

Output:     Executive outcomes.0---succeed. *******************************************************/ static s32 gtp_cover_panel(struct i2c_client *client) {     s32 ret = 0;

#if GTP_DRIVER_SEND_CFG     s32 i;     u8 check_sum = 0;     u8 opr_buf[16];     u8 sensor_id = 0;   u8 drv_cfg_version;   u8 flash_cfg_version;

    u8 cfg_cover_info_group0[] = CTP_CFG_COVER_GROUP0;     u8 cfg_cover_info_group1[] = CTP_CFG_COVER_GROUP1;     u8 cfg_cover_info_group2[] = CTP_CFG_COVER_GROUP2;     u8 cfg_cover_info_group3[] = CTP_CFG_COVER_GROUP3;     u8 cfg_cover_info_group4[] = CTP_CFG_COVER_GROUP4;     u8 cfg_cover_info_group5[] = CTP_CFG_COVER_GROUP5;     u8 *send_cover_cfg_buf[] = {cfg_cover_info_group0, cfg_cover_info_group1, cfg_cover_info_group2,                         cfg_cover_info_group3, cfg_cover_info_group4, cfg_cover_info_group5};     u8 cfg_cover_info_len[] = { CFG_GROUP_LEN(cfg_cover_info_group0),                           CFG_GROUP_LEN(cfg_cover_info_group1),                           CFG_GROUP_LEN(cfg_cover_info_group2),                           CFG_GROUP_LEN(cfg_cover_info_group3),                           CFG_GROUP_LEN(cfg_cover_info_group4),                           CFG_GROUP_LEN(cfg_cover_info_group5)}; #if GTP_CHARGER_SWITCH  const u8 cfg_cover_grp0_charger[] = GTP_CFG_COVER_GROUP0_CHARGER;  const u8 cfg_cover_grp1_charger[] = GTP_CFG_COVER_GROUP1_CHARGER;  const u8 cfg_cover_grp2_charger[] = GTP_CFG_COVER_GROUP2_CHARGER;  const u8 cfg_cover_grp3_charger[] = GTP_CFG_COVER_GROUP3_CHARGER;  const u8 cfg_cover_grp4_charger[] = GTP_CFG_COVER_GROUP4_CHARGER;  const u8 cfg_cover_grp5_charger[] = GTP_CFG_COVER_GROUP5_CHARGER;  const u8 *cfgs_cover_charger[] = {   cfg_cover_grp0_charger, cfg_cover_grp1_charger, cfg_cover_grp2_charger,   cfg_cover_grp3_charger, cfg_cover_grp4_charger, cfg_cover_grp5_charger  };  u8 cfg_cover_lens_charger[] = {       CFG_GROUP_LEN(cfg_cover_grp0_charger),       CFG_GROUP_LEN(cfg_cover_grp1_charger),       CFG_GROUP_LEN(cfg_cover_grp2_charger),       CFG_GROUP_LEN(cfg_cover_grp3_charger),       CFG_GROUP_LEN(cfg_cover_grp4_charger),       CFG_GROUP_LEN(cfg_cover_grp5_charger)}; #endif

    GTP_DEBUG("Config Groups\' Lengths: %d, %d, %d, %d, %d, %d",         cfg_cover_info_len[0], cfg_cover_info_len[1], cfg_cover_info_len[2], cfg_cover_info_len[3],         cfg_cover_info_len[4], cfg_cover_info_len[5]);

    if ((!cfg_cover_info_len[1]) && (!cfg_cover_info_len[2]) &&         (!cfg_cover_info_len[3]) && (!cfg_cover_info_len[4]) &&         (!cfg_cover_info_len[5]))     {         sensor_id = 0;     }     else     {     #if GTP_COMPATIBLE_MODE         if (CHIP_TYPE_GT9F == gtp_chip_type)         {             msleep(50);         }     #endif         ret = gtp_i2c_read_dbl_check(client, GTP_REG_SENSOR_ID, &sensor_id, 1);         if (SUCCESS == ret)         {             if (sensor_id >= 0x06)             {                 GTP_ERROR("Invalid sensor_id(0x%02X), No Config Sent!", sensor_id);                 pnl_cover_init_error = 1;                 return -1;             }         }         else         {             GTP_ERROR("Failed to get sensor_id, No config sent!");             pnl_cover_init_error = 1;             return -1;         }         GTP_INFO("Sensor_ID: %d", sensor_id);     }         cfg_cover_len = cfg_cover_info_len[sensor_id];         GTP_INFO("CTP_CONFIG_GROUP%d used, config length: %d", sensor_id, cfg_cover_len);         if (cfg_cover_len < GTP_CONFIG_MIN_LENGTH)     {         GTP_ERROR("CTP_CONFIG_GROUP%d is INVALID CONFIG GROUP! NO Config Sent! You need to check you header file CFG_GROUP section!", sensor_id);         pnl_cover_init_error = 1;         return -1;     }     #if GTP_COMPATIBLE_MODE     if (CHIP_TYPE_GT9F != gtp_chip_type) #endif  {      ret = gtp_i2c_read_dbl_check(client, GTP_REG_CONFIG_DATA, &opr_buf[0], 1);         if (ret == SUCCESS)      {          GTP_DEBUG("CFG_CONFIG_GROUP%d Config Version: %d, 0x%02X; IC Config Version: %d, 0x%02X", sensor_id,                      send_cover_cfg_buf[sensor_id][0], send_cover_cfg_buf[sensor_id][0], opr_buf[0], opr_buf[0]);      flash_cfg_version = opr_buf[0];    drv_cfg_version = send_cover_cfg_buf[sensor_id][0];       // backup  config version              if (flash_cfg_version < 90 && flash_cfg_version > drv_cfg_version) {              send_cover_cfg_buf[sensor_id][0] = 0x00;          }      }      else      {          GTP_ERROR("Failed to get ic config version!No config sent!");          return -1;      }  }      memset(&config_cover[GTP_ADDR_LENGTH], 0, GTP_CONFIG_MAX_LENGTH);     memcpy(&config_cover[GTP_ADDR_LENGTH], send_cover_cfg_buf[sensor_id], cfg_cover_len);

#if GTP_CUSTOM_CFG     config_cover[RESOLUTION_LOC]     = (u8)GTP_MAX_WIDTH;     config_cover[RESOLUTION_LOC + 1] = (u8)(GTP_MAX_WIDTH>>8);     config_cover[RESOLUTION_LOC + 2] = (u8)GTP_MAX_HEIGHT;     config_cover[RESOLUTION_LOC + 3] = (u8)(GTP_MAX_HEIGHT>>8);         if (GTP_INT_TRIGGER == 0)  //RISING     {         config_cover[TRIGGER_LOC] &= 0xfe;     }     else if (GTP_INT_TRIGGER == 1)  //FALLING     {         config_cover[TRIGGER_LOC] |= 0x01;     } #endif  // GTP_CUSTOM_CFG

 check_sum = 0;  for (i = GTP_ADDR_LENGTH; i < cfg_cover_len; i++)  {   check_sum += config_cover[i];  }  config_cover[cfg_cover_len] = (~check_sum) + 1;

#if GTP_CHARGER_SWITCH  GTP_DEBUG("Charger Config Groups Length: %d, %d, %d, %d, %d, %d", cfg_cover_lens_charger[0],     cfg_cover_lens_charger[1], cfg_cover_lens_charger[2], cfg_cover_lens_charger[3], cfg_cover_lens_charger[4], cfg_cover_lens_charger[5]);

 memset(&gtp_charger_config_cover[GTP_ADDR_LENGTH], 0, GTP_CONFIG_MAX_LENGTH);  if (cfg_cover_lens_charger[sensor_id] == cfg_cover_len)   memcpy(&gtp_charger_config_cover[GTP_ADDR_LENGTH], cfgs_cover_charger[sensor_id], cfg_cover_len);

#if GTP_CUSTOM_CFG  gtp_charger_config_cover[RESOLUTION_LOC] = (u8) GTP_MAX_WIDTH;  gtp_charger_config_cover[RESOLUTION_LOC + 1] = (u8) (GTP_MAX_WIDTH >> 8);  gtp_charger_config_cover[RESOLUTION_LOC + 2] = (u8) GTP_MAX_HEIGHT;  gtp_charger_config_cover[RESOLUTION_LOC + 3] = (u8) (GTP_MAX_HEIGHT >> 8);

 if (GTP_INT_TRIGGER == 0)  /* RISING  */   gtp_charger_config_cover[TRIGGER_LOC] &= 0xfe;  else if (GTP_INT_TRIGGER == 1) /* FALLING */   gtp_charger_config_cover[TRIGGER_LOC] |= 0x01; #endif /* END GTP_CUSTOM_CFG */  if (cfg_cover_lens_charger[sensor_id] != cfg_cover_len)   memset(&gtp_charger_config_cover[GTP_ADDR_LENGTH], 0, GTP_CONFIG_MAX_LENGTH);     check_sum = 0;  for (i = GTP_ADDR_LENGTH; i < cfg_cover_len; i++)  {   check_sum += gtp_charger_config_cover[i];  }  gtp_charger_config_cover[cfg_cover_len] = (~check_sum) + 1;

#endif /* END GTP_CHARGER_SWITCH */      #else // DRIVER NOT SEND CONFIG     cfg_cover_len = GTP_CONFIG_MAX_LENGTH;     ret = gtp_i2c_read(client, config_cover, cfg_cover_len + GTP_ADDR_LENGTH);     if (ret < 0)     {         GTP_ERROR("Read Config Failed, Using DEFAULT Resolution & INT Trigger!");         abs_x_max = GTP_MAX_WIDTH;         abs_y_max = GTP_MAX_HEIGHT;         int_type = GTP_INT_TRIGGER;     } #endif // GTP_DRIVER_SEND_CFG

    GTP_DEBUG_FUNC();     if ((abs_x_max == 0) && (abs_y_max == 0))     {         abs_x_max = (config_cover[RESOLUTION_LOC + 1] << 8) + config_cover[RESOLUTION_LOC];         abs_y_max = (config_cover[RESOLUTION_LOC + 3] << 8) + config_cover[RESOLUTION_LOC + 2];         int_type = (config_cover[TRIGGER_LOC]) & 0x03;     }     #if GTP_COMPATIBLE_MODE     if (CHIP_TYPE_GT9F == gtp_chip_type)     {         u8 have_key = 0;         if (is_950)         {             driver_num_cover = config_cover[GTP_REG_MATRIX_DRVNUM - GTP_REG_CONFIG_DATA + 2];             sensor_num_cover = config_cover[GTP_REG_MATRIX_SENNUM - GTP_REG_CONFIG_DATA + 2];         }         else         {             driver_num_cover = (config_cover[CFG_LOC_DRVA_NUM]&0x1F) + (config_cover[CFG_LOC_DRVB_NUM]&0x1F);             sensor_num_cover = (config_cover[CFG_LOC_SENS_NUM]&0x0F) + ((config_cover[CFG_LOC_SENS_NUM]>>4)&0x0F);         }                 have_key = config_cover[GTP_REG_HAVE_KEY - GTP_REG_CONFIG_DATA + 2] & 0x01;  // have key or not         if (1 == have_key)         {             driver_num_cover--;         }                 GTP_INFO("Driver * Sensor: %d * %d(Key: %d), X_MAX = %d, Y_MAX = %d, TRIGGER = 0x%02x",             driver_num_cover, sensor_num_cover, have_key, abs_x_max,abs_y_max,int_type);     }     else #endif     { #if GTP_DRIVER_SEND_CFG #if GTP_COMPATIBLE_MODE      if (CHIP_TYPE_GT9F != gtp_chip_type) #endif    {         /* for resume to send config */   if (flash_cfg_version < 90 && flash_cfg_version > drv_cfg_version) {            config_cover[GTP_ADDR_LENGTH] = drv_cfg_version;          check_sum = 0;          for (i = GTP_ADDR_LENGTH; i < cfg_cover_len; i++)          {              check_sum += config_cover[i];          }          config_cover[cfg_cover_len] = (~check_sum) + 1;   }    } #endif         GTP_INFO("X_MAX = %d, Y_MAX = %d, TRIGGER = 0x%02x",             abs_x_max,abs_y_max,int_type);     }         msleep(10);     return 0; }

static s8 gtp_i2c_test(struct i2c_client *client) {

    u8 retry = 0;     s8 ret = -1;     u32 hw_info = 0;

    GTP_DEBUG_FUNC();

    while (retry++ < 5)     {         ret = i2c_read_bytes(client, GTP_REG_HW_INFO, (u8 *)&hw_info, sizeof(hw_info));

        if ((!ret) && (hw_info == 0x00900600))              //20121212         {             return ret;         }

        GTP_ERROR("GTP_REG_HW_INFO : %08X", hw_info);         GTP_ERROR("GTP i2c test failed time %d.", retry);         msleep(10);     }

    return -1; }

 

/******************************************************* Function:     Set INT pin  as input for FW sync.

Note:   If the INT is high, It means there is pull up resistor attached on the INT pin.   Pull low the INT pin manaully for FW sync. *******************************************************/ void gtp_int_sync(s32 ms) {     GTP_GPIO_OUTPUT(GTP_INT_PORT, 0);     msleep(ms);     GTP_GPIO_AS_INT(GTP_INT_PORT); }

void gtp_reset_guitar(struct i2c_client *client, s32 ms) {     GTP_INFO("GTP RESET!\n");     GTP_GPIO_OUTPUT(GTP_RST_PORT, 0);     msleep(ms);     GTP_GPIO_OUTPUT(GTP_INT_PORT, client->addr == 0x14);

    msleep(2);     GTP_GPIO_OUTPUT(GTP_RST_PORT, 1);

    msleep(6);                      //must >= 6ms

#if GTP_COMPATIBLE_MODE     if (CHIP_TYPE_GT9F == gtp_chip_type)     {         return;     } #endif

    gtp_int_sync(50); #if GTP_ESD_PROTECT     gtp_init_ext_watchdog(i2c_client_point); #endif }

static int tpd_power_on(struct i2c_client *client) {     int ret = 0;     int reset_count = 0;

reset_proc:     GTP_GPIO_OUTPUT(GTP_RST_PORT, 0);       GTP_GPIO_OUTPUT(GTP_INT_PORT, 0);     msleep(10);

#ifdef MT6573     // power on CTP     mt_set_gpio_mode(GPIO_CTP_EN_PIN, GPIO_CTP_EN_PIN_M_GPIO);     mt_set_gpio_dir(GPIO_CTP_EN_PIN, GPIO_DIR_OUT);     mt_set_gpio_out(GPIO_CTP_EN_PIN, GPIO_OUT_ONE);

#else   // ( defined(MT6575) || defined(MT6577) || defined(MT6589) )

    #ifdef TPD_POWER_SOURCE_CUSTOM                                   hwPowerOn(TPD_POWER_SOURCE_CUSTOM, VOL_2800, "TP");        #else         hwPowerOn(MT65XX_POWER_LDO_VGP2, VOL_2800, "TP");     #endif     #ifdef TPD_POWER_SOURCE_1800         hwPowerOn(TPD_POWER_SOURCE_1800, VOL_1800, "TP");     #endif

#endif

    gtp_reset_guitar(client, 20);

#if GTP_COMPATIBLE_MODE     gtp_get_chip_type(client);         if (CHIP_TYPE_GT9F == gtp_chip_type)     {         ret = gup_fw_download_proc(NULL, GTP_FL_FW_BURN);             if(FAIL == ret)         {             GTP_ERROR("[tpd_power_on]Download fw failed.");             if(reset_count++ < TPD_MAX_RESET_COUNT)             {                 goto reset_proc;             }             else             {                 return -1;             }         }                 ret = gtp_fw_startup(client);         if(FAIL == ret)         {             GTP_ERROR("[tpd_power_on]Startup fw failed.");             if(reset_count++ < TPD_MAX_RESET_COUNT)             {                 goto reset_proc;             }             else             {                 return -1;             }         }     }     else  #endif     {         ret = gtp_i2c_test(client);             if (ret < 0)         {             GTP_ERROR("I2C communication ERROR!");                 if (reset_count < TPD_MAX_RESET_COUNT)             {                 reset_count++;                 goto reset_proc;             }         }     }     return ret; }

void gtp_irq_enable(void) {  if(irq_flag==0){   irq_flag++; #ifdef CONFIG_OF_TOUCH   enable_irq(touch_irq); #else   mt_eint_unmask(CUST_EINT_TOUCH_PANEL_NUM); #endif  }else{   GTP_INFO("Touch Eint already enabled!");  }  //GTP_INFO("Enable irq_flag=%d",irq_flag);

} void gtp_irq_disable(void) {  if(irq_flag==1){   irq_flag--; #ifdef CONFIG_OF_TOUCH   disable_irq(touch_irq); #else   mt_eint_mask(CUST_EINT_TOUCH_PANEL_NUM); #endif  }else{   GTP_INFO("Touch Eint already disabled!");  }  //GTP_INFO("Disable irq_flag=%d",irq_flag); }

#ifdef CONFIG_OF_TOUCH static int tpd_irq_registration(void) {  struct device_node *node = NULL;  int ret = 0;  u32 ints[2] = {0,0};  GTP_INFO("Device Tree Tpd_irq_registration!");    node = of_find_compatible_node(NULL, NULL, "mediatek, TOUCH_PANEL-eint");  if(node){   of_property_read_u32_array(node , "debounce", ints, ARRAY_SIZE(ints));   gpio_set_debounce(ints[0], ints[1]);

  touch_irq = irq_of_parse_and_map(node, 0);   GTP_INFO("Device gtp_int_type = %d!", int_type);   if (!int_type) //EINTF_TRIGGER   {    ret = request_irq(touch_irq, (irq_handler_t)tpd_eint_interrupt_handler, EINTF_TRIGGER_RISING, "TOUCH_PANEL-eint", NULL);             //gtp_eint_trigger_type = EINTF_TRIGGER_RISING;    if(ret > 0){        ret = -1;        GTP_ERROR("tpd request_irq IRQ LINE NOT AVAILABLE!.");    }   }   else   {    ret = request_irq(touch_irq, (irq_handler_t)tpd_eint_interrupt_handler, EINTF_TRIGGER_FALLING, "TOUCH_PANEL-eint", NULL);             //gtp_eint_trigger_type = EINTF_TRIGGER_FALLING;    if(ret > 0){        ret = -1;        GTP_ERROR("tpd request_irq IRQ LINE NOT AVAILABLE!.");    }   }  }else{   GTP_ERROR("tpd request_irq can not find touch eint device node!.");   ret = -1;  }  GTP_INFO("[%s]irq:%d, debounce:%d-%d:", __FUNCTION__, touch_irq, ints[0], ints[1]);  return ret; } #endif

//**************** For GT9XXF Start ********************// #if GTP_COMPATIBLE_MODE

void gtp_get_chip_type(struct i2c_client *client) {     u8 opr_buf[10] = {0x00};     s32 ret = 0;         msleep(10);         ret = gtp_i2c_read_dbl_check(client, GTP_REG_CHIP_TYPE, opr_buf, 10);         if (FAIL == ret)     {         GTP_ERROR("Failed to get chip-type, set chip type default: GOODIX_GT9");         gtp_chip_type = CHIP_TYPE_GT9;         return;     }         if (!memcmp(opr_buf, "GOODIX_GT9", 10))     {         gtp_chip_type = CHIP_TYPE_GT9;     }     else // GT9XXF     {         gtp_chip_type = CHIP_TYPE_GT9F;     }     GTP_INFO("Chip Type: %s", (gtp_chip_type == CHIP_TYPE_GT9) ? "GOODIX_GT9" : "GOODIX_GT9F"); }

static u8 gtp_bak_ref_proc(struct i2c_client *client, u8 mode) {     s32 i = 0;     s32 j = 0;     s32 ret = 0;     struct file *flp = NULL;     u8 *refp = NULL;     u32 ref_len = 0;     u32 ref_seg_len = 0;     s32 ref_grps = 0;     s32 ref_chksum = 0;     u16 tmp = 0;         GTP_DEBUG("[gtp_bak_ref_proc]Driver:%d,Sensor:%d.", driver_num, sensor_num);

    //check file-system mounted     GTP_DEBUG("[gtp_bak_ref_proc]Waiting for FS %d", gtp_ref_retries);            if (gup_check_fs_mounted("/data") == FAIL)            {         GTP_DEBUG("[gtp_bak_ref_proc]/data not mounted");         if(gtp_ref_retries++ < GTP_CHK_FS_MNT_MAX)         {             return FAIL;         }     }     else     {         GTP_DEBUG("[gtp_bak_ref_proc]/data mounted !!!!");     }         if (is_950)     {         ref_seg_len = (driver_num * (sensor_num - 1) + 2) * 2;         ref_grps = 6;         ref_len =  ref_seg_len * 6;  // for GT950, backup-reference for six segments     }     else     {         ref_len = driver_num*(sensor_num-2)*2 + 4;         ref_seg_len = ref_len;         ref_grps = 1;     }         refp = (u8 *)kzalloc(ref_len, GFP_KERNEL);     if(refp == NULL)     {         GTP_ERROR("Failed to allocate memory for reference buffer!");         return FAIL;     }     memset(refp, 0, ref_len);         //get ref file data     flp = filp_open(GTP_BAK_REF_PATH, O_RDWR | O_CREAT, 0666);     if (IS_ERR(flp))     {         GTP_ERROR("Failed to open/create %s.", GTP_BAK_REF_PATH);         if (GTP_BAK_REF_SEND == mode)         {             goto default_bak_ref;         }         else         {             goto exit_ref_proc;         }     }         switch (mode)     {     case GTP_BAK_REF_SEND:         {             flp->f_op->llseek(flp, 0, SEEK_SET);             ret = flp->f_op->read(flp, (char *)refp, ref_len, &flp->f_pos);             if(ret < 0)             {                 GTP_ERROR("Read ref file failed, send default bak ref.");                 goto default_bak_ref;             }             //checksum ref file             for (j = 0; j < ref_grps; ++j)             {                 ref_chksum = 0;                 for(i=0; i<ref_seg_len-2; i+=2)                 {                     ref_chksum += ((refp[i + j * ref_seg_len]<<8) + refp[i + 1 + j * ref_seg_len]);                 }                             GTP_DEBUG("Reference chksum:0x%04X", ref_chksum&0xFF);                 tmp = ref_chksum + (refp[ref_seg_len + j * ref_seg_len -2]<<8) + refp[ref_seg_len + j * ref_seg_len -1];                 if(1 != tmp)                 {                     GTP_DEBUG("Invalid checksum for reference, reset reference.");                     memset(&refp[j * ref_seg_len], 0, ref_seg_len);                     refp[ref_seg_len - 1 + j * ref_seg_len] = 0x01;                 }                 else                 {                     if (j == (ref_grps - 1))                     {                         GTP_INFO("Reference data in %s used.", GTP_BAK_REF_PATH);                     }                 }                           }             ret = i2c_write_bytes(client, GTP_REG_BAK_REF, refp, ref_len);             if(-1 == ret)             {                 GTP_ERROR("Write ref i2c error.");                 ret = FAIL;                 goto exit_ref_proc;             }         }         break;             case GTP_BAK_REF_STORE:         {             ret = i2c_read_bytes(client, GTP_REG_BAK_REF, refp, ref_len);             if(-1 == ret)             {                 GTP_ERROR("Read ref i2c error.");                 ret = FAIL;                 goto exit_ref_proc;             }             flp->f_op->llseek(flp, 0, SEEK_SET);             flp->f_op->write(flp, (char *)refp, ref_len, &flp->f_pos);         }         break;             default:         GTP_ERROR("Invalid Argument(%d) for backup reference", mode);         ret = FAIL;         goto exit_ref_proc;     }         ret = SUCCESS;     goto exit_ref_proc;

default_bak_ref:     for (j = 0; j < ref_grps; ++j)     {         memset(&refp[j * ref_seg_len], 0, ref_seg_len);         refp[j * ref_seg_len + ref_seg_len - 1] = 0x01;  // checksum = 1     }     ret = i2c_write_bytes(client, GTP_REG_BAK_REF, refp, ref_len);     if (flp && !IS_ERR(flp))     {         GTP_INFO("Write backup-reference data into %s", GTP_BAK_REF_PATH);         flp->f_op->llseek(flp, 0, SEEK_SET);         flp->f_op->write(flp, (char*)refp, ref_len, &flp->f_pos);     }     if (ret < 0)     {         GTP_ERROR("Failed to load the default backup reference");         ret = FAIL;     }     else     {         ret = SUCCESS;     } exit_ref_proc:     if (refp)     {         kfree(refp);     }     if (flp && !IS_ERR(flp))     {         filp_close(flp, NULL);     }     return ret; }

u8 gtp_fw_startup(struct i2c_client *client) {     u8 wr_buf[4];     s32 ret = 0;         //init sw WDT     wr_buf[0] = 0xAA;     ret = i2c_write_bytes(client, 0x8041, wr_buf, 1);     if (ret < 0)     {         GTP_ERROR("I2C error to firmware startup.");         return FAIL;     }     //release SS51 & DSP     wr_buf[0] = 0x00;     i2c_write_bytes(client, 0x4180, wr_buf, 1);         //int sync     gtp_int_sync(25);         //check fw run status     i2c_read_bytes(client, 0x8041, wr_buf, 1);     if(0xAA == wr_buf[0])     {         GTP_ERROR("IC works abnormally,startup failed.");         return FAIL;     }     else     {         GTP_DEBUG("IC works normally,Startup success.");         wr_buf[0] = 0xAA;         i2c_write_bytes(client, 0x8041, wr_buf, 1);         return SUCCESS;     } }

static void gtp_recovery_reset(struct i2c_client *client) { #if GTP_ESD_PROTECT     gtp_esd_switch(client, SWITCH_OFF); #endif     force_reset_guitar(); #if GTP_ESD_PROTECT     gtp_esd_switch(client, SWITCH_ON); #endif }

static u8 gtp_check_clk_legality(u8 *p_clk_buf) {     u8 i = 0;     u8 clk_chksum = p_clk_buf[5];         for(i = 0; i < 5; i++)     {         if((p_clk_buf[i] < 50) || (p_clk_buf[i] > 120) ||             (p_clk_buf[i] != p_clk_buf[0]))         {             break;         }         clk_chksum += p_clk_buf[i];     }         if((i == 5) && (clk_chksum == 0))     {         GTP_DEBUG("Valid main clock data.");         return SUCCESS;     }     GTP_ERROR("Invalid main clock data.");     return FAIL; }

static u8 gtp_main_clk_proc(struct i2c_client *client) {     s32 ret = 0;     u8  i = 0;     u8  clk_cal_result = 0;     u8  clk_chksum = 0;     u8  gtp_clk_buf[6] = {0};     struct file *flp = NULL;         GTP_DEBUG("[gtp_main_clk_proc]Waiting for FS %d", gtp_ref_retries);            if (gup_check_fs_mounted("/data") == FAIL)            {                    GTP_DEBUG("[gtp_main_clk_proc]/data not mounted");         if(gtp_clk_retries++ < GTP_CHK_FS_MNT_MAX)         {             return FAIL;         }         else         {             GTP_ERROR("[gtp_main_clk_proc]Wait for file system timeout,need cal clk");         }     }     else     {         GTP_DEBUG("[gtp_main_clk_proc]/data mounted !!!!");         flp = filp_open(GTP_MAIN_CLK_PATH, O_RDWR | O_CREAT, 0666);         if (!IS_ERR(flp))         {             flp->f_op->llseek(flp, 0, SEEK_SET);             ret = flp->f_op->read(flp, (char *)gtp_clk_buf, 6, &flp->f_pos);             if(ret > 0)             {                 ret = gtp_check_clk_legality(gtp_clk_buf);                 if(SUCCESS == ret)                 {                         GTP_DEBUG("[gtp_main_clk_proc]Open & read & check clk file success.");                     goto send_main_clk;                 }             }         }         GTP_ERROR("[gtp_main_clk_proc]Check clk file failed,need cal clk");     }         //cal clk #if GTP_ESD_PROTECT     gtp_esd_switch(client, SWITCH_OFF); #endif     clk_cal_result = gup_clk_calibration();     force_reset_guitar();     GTP_DEBUG("&&&&&&&&&&clk cal result:%d", clk_cal_result);     #if GTP_ESD_PROTECT     gtp_esd_switch(client, SWITCH_ON); #endif 

    if(clk_cal_result < 50 || clk_cal_result > 120)     {         GTP_ERROR("Invalid main clock: %d", clk_cal_result);         ret = FAIL;         goto exit_clk_proc;     }         for(i = 0;i < 5; i++)     {         gtp_clk_buf[i] = clk_cal_result;         clk_chksum += gtp_clk_buf[i];     }     gtp_clk_buf[5] = 0 - clk_chksum;     send_main_clk:         ret = i2c_write_bytes(client, 0x8020, gtp_clk_buf, 6);         if (flp && !IS_ERR(flp))     {         flp->f_op->llseek(flp, 0, SEEK_SET);         flp->f_op->write(flp, (char *)gtp_clk_buf, 6, &flp->f_pos);     }         if(-1 == ret)     {         GTP_ERROR("[gtp_main_clk_proc]send main clk i2c error!");         ret = FAIL;     }     else     {         ret = SUCCESS;     }     exit_clk_proc:     if (flp && !IS_ERR(flp))     {         filp_close(flp, NULL);     }     return ret; }

#endif //************* For GT9XXF End **********************//

#if GTP_WITH_PEN static void gtp_pen_init(void) {     s32 ret = 0;         pen_dev = input_allocate_device();     if (pen_dev == NULL)     {         GTP_ERROR("Failed to allocate input device for pen/stylus.");         return;     }         pen_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) ;     pen_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);         set_bit(BTN_TOOL_PEN, pen_dev->keybit);     set_bit(INPUT_PROP_DIRECT, pen_dev->propbit);     //set_bit(INPUT_PROP_POINTER, pen_dev->propbit);     #if GTP_PEN_HAVE_BUTTON     input_set_capability(pen_dev, EV_KEY, BTN_STYLUS);     input_set_capability(pen_dev, EV_KEY, BTN_STYLUS2); #endif

    input_set_abs_params(pen_dev, ABS_MT_POSITION_X, 0, TPD_RES_X, 0, 0);     input_set_abs_params(pen_dev, ABS_MT_POSITION_Y, 0, TPD_RES_Y, 0, 0);     input_set_abs_params(pen_dev, ABS_MT_PRESSURE, 0, 255, 0, 0);     input_set_abs_params(pen_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);     input_set_abs_params(pen_dev, ABS_MT_TRACKING_ID, 0, 255, 0, 0);         pen_dev->name = "mtk-pen";     pen_dev->phys = "input/ts";     pen_dev->id.bustype = BUS_I2C;         ret = input_register_device(pen_dev);     if (ret)     {         GTP_ERROR("Register %s input device failed", pen_dev->name);         return;     } }

static void gtp_pen_down(s32 x, s32 y, s32 size, s32 id) {     input_report_key(pen_dev, BTN_TOOL_PEN, 1);     input_report_key(pen_dev, BTN_TOUCH, 1);     input_report_abs(pen_dev, ABS_MT_POSITION_X, x);     input_report_abs(pen_dev, ABS_MT_POSITION_Y, y);     if ((!size) && (!id))     {         input_report_abs(pen_dev, ABS_MT_PRESSURE, 100);         input_report_abs(pen_dev, ABS_MT_TOUCH_MAJOR, 100);     }     else     {         input_report_abs(pen_dev, ABS_MT_PRESSURE, size);         input_report_abs(pen_dev, ABS_MT_TOUCH_MAJOR, size);         input_report_abs(pen_dev, ABS_MT_TRACKING_ID, id);     }     input_mt_sync(pen_dev); }

static void gtp_pen_up(void) {     input_report_key(pen_dev, BTN_TOOL_PEN, 0);     input_report_key(pen_dev, BTN_TOUCH, 0); } #endif

static s32 tpd_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) {     s32 err = 0;     s32 ret = 0;

    u16 version_info;   #if GTP_HAVE_TOUCH_KEY     s32 idx = 0; #endif #ifdef TPD_PROXIMITY     struct hwmsen_object obj_ps; #endif

    if (RECOVERY_BOOT == get_boot_mode())             return 0;

    i2c_client_point = client;     ret = tpd_power_on(client);

    if (ret < 0)     {         GTP_ERROR("I2C communication ERROR!");     }     //#ifdef VELOCITY_CUSTOM #if 0     if ((err = misc_register(&tpd_misc_device)))     {         printk("mtk_tpd: tpd_misc_device register failed\n");     }

#endif     ret = gtp_read_version(client, &version_info);

    if (ret < 0)     {         GTP_ERROR("Read version failed.");     }            ret = gtp_init_panel(client);

    if (ret < 0)     {         GTP_ERROR("GTP init panel failed.");     }   #if GTP_COVER_CONTROL     ret = gtp_cover_panel(client);

    if (ret < 0)     {         GTP_ERROR("GTP cover panel failed.");     } #endif         // Create proc file system     gt91xx_config_proc = proc_create(GT91XX_CONFIG_PROC_FILE, 0644, NULL, &config_proc_ops);     if (gt91xx_config_proc == NULL)     {         GTP_ERROR("create_proc_entry %s failed\n", GT91XX_CONFIG_PROC_FILE);     }     else     {         GTP_INFO("create proc entry %s success", GT91XX_CONFIG_PROC_FILE);     }  //add by chen for MX gesture    mx_tsp=root_device_register("mx_tsp");

 err = sysfs_create_group(&mx_tsp->kobj,&gesture_attribute_group);  if (err < 0)  {     GTP_ERROR("unable to create gesture attribute file\n");  }

 //add end

#if GTP_COVER_CONTROL  err =register_cover_notifier(&cover_notifier1);    if (err)    {         GTP_ERROR("register cover_notifier1 error\n");    } #endif

#if GTP_P_GESTURE_CONTROL  err =register_gesture_notifier(&gesture_notifier1);    if (err)    {         GTP_ERROR("register gesture_notifier1 error\n");    } #endif

#if GTP_CREATE_WR_NODE     init_wr_node(client); #endif

    thread = kthread_run(touch_event_handler, 0, TPD_DEVICE);

    if (IS_ERR(thread))     {         err = PTR_ERR(thread);         GTP_INFO(TPD_DEVICE " failed to create kernel thread: %d\n", err);     }         #if GTP_HAVE_TOUCH_KEY

    for (idx = 0; idx < GTP_MAX_KEY_NUM; idx++)     {         input_set_capability(tpd->dev, EV_KEY, touch_key_array[idx]);     }

#endif #if GTP_GESTURE_WAKEUP //    input_set_capability(tpd->dev, EV_KEY, KEY_POWER);     input_set_capability(tpd->dev, EV_KEY, KEY_GESTURE); #endif     #if GTP_WITH_PEN     gtp_pen_init(); #endif     // set INT mode     mt_set_gpio_mode(GPIO_CTP_EINT_PIN, GPIO_CTP_EINT_PIN_M_EINT);     mt_set_gpio_dir(GPIO_CTP_EINT_PIN, GPIO_DIR_IN);     mt_set_gpio_pull_enable(GPIO_CTP_EINT_PIN, GPIO_PULL_DISABLE);

    msleep(50);

#ifdef CONFIG_OF_TOUCH  /* EINT device tree, default EINT enable */  tpd_irq_registration(); #else

#ifdef MT6572     if (!int_type)  //EINTF_TRIGGER     {         mt_eint_registration(CUST_EINT_TOUCH_PANEL_NUM, EINTF_TRIGGER_RISING, tpd_eint_interrupt_handler, 1);     }     else     {         mt_eint_registration(CUST_EINT_TOUCH_PANEL_NUM, EINTF_TRIGGER_FALLING, tpd_eint_interrupt_handler, 1);     }     #else     mt65xx_eint_set_sens(CUST_EINT_TOUCH_PANEL_NUM, CUST_EINT_TOUCH_PANEL_SENSITIVE);     mt65xx_eint_set_hw_debounce(CUST_EINT_TOUCH_PANEL_NUM, CUST_EINT_TOUCH_PANEL_DEBOUNCE_CN);

    if (!int_type)     {         mt65xx_eint_registration(CUST_EINT_TOUCH_PANEL_NUM, CUST_EINT_TOUCH_PANEL_DEBOUNCE_EN, CUST_EINT_POLARITY_HIGH, tpd_eint_interrupt_handler, 1);     }     else     {         mt65xx_eint_registration(CUST_EINT_TOUCH_PANEL_NUM, CUST_EINT_TOUCH_PANEL_DEBOUNCE_EN, CUST_EINT_POLARITY_LOW, tpd_eint_interrupt_handler, 1);     } #endif #endif   gtp_irq_enable(); #if GTP_ESD_PROTECT     gtp_esd_switch(client, SWITCH_ON); #endif

#if GTP_AUTO_UPDATE     ret = gup_init_update_proc(client);

    if (ret < 0)     {         GTP_ERROR("Create update thread error.");     } #endif

#ifdef TPD_PROXIMITY     //obj_ps.self = cm3623_obj;     obj_ps.polling = 0;         //0--interrupt mode;1--polling mode;     obj_ps.sensor_operate = tpd_ps_operate;

    if ((err = hwmsen_attach(ID_PROXIMITY, &obj_ps)))     {         GTP_ERROR("hwmsen attach fail, return:%d.", err);     }

#endif

       tpd_load_status = 1;

    return 0; }

#ifdef CONFIG_OF_TOUCH static irqreturn_t tpd_eint_interrupt_handler(unsigned irq, struct irq_desc *desc) {  TPD_DEBUG_PRINT_INT;     tpd_flag = 1;  /* enter EINT handler disable INT, make sure INT is disable when handle touch event including top/bottom half */  /* use _nosync to avoid deadlock */  //disable_irq_nosync(touch_irq);  //irq_flag--;  //GTP_INFO("disable irq_flag=%d",irq_flag);  wake_up_interruptible(&waiter);     return IRQ_HANDLED; } #else static void tpd_eint_interrupt_handler(void) {  TPD_DEBUG_PRINT_INT;

 tpd_flag = 1;

 wake_up_interruptible(&waiter); } #endif /* static void tpd_eint_interrupt_handler(void) {     TPD_DEBUG_PRINT_INT;         tpd_flag = 1;         wake_up_interruptible(&waiter); }*/

static int tpd_i2c_remove(struct i2c_client *client) { #if GTP_CREATE_WR_NODE     uninit_wr_node(); #endif

#if GTP_ESD_PROTECT     destroy_workqueue(gtp_esd_check_workqueue); #endif     sysfs_remove_group(&mx_tsp->kobj,&gesture_attribute_group);     root_device_unregister(mx_tsp);

    return 0; } #if (GTP_ESD_PROTECT || GTP_COMPATIBLE_MODE) static void force_reset_guitar(void) {     s32 i = 0;     s32 ret = 0;

    GTP_INFO("force_reset_guitar");         //mt65xx_eint_mask(CUST_EINT_TOUCH_PANEL_NUM);  gtp_irq_disable();        GTP_GPIO_OUTPUT(GTP_RST_PORT, 0);       GTP_GPIO_OUTPUT(GTP_INT_PORT, 0); #ifdef MT6573     //Power off TP     mt_set_gpio_mode(GPIO_CTP_EN_PIN, GPIO_CTP_EN_PIN_M_GPIO);     mt_set_gpio_dir(GPIO_CTP_EN_PIN, GPIO_DIR_OUT);     mt_set_gpio_out(GPIO_CTP_EN_PIN, GPIO_OUT_ZERO);      msleep(30);     //Power on TP     mt_set_gpio_out(GPIO_CTP_EN_PIN, GPIO_OUT_ONE);     msleep(30); #else           // ( defined(MT6575) || defined(MT6577) || defined(MT6589) )     // Power off TP     #ifdef TPD_POWER_SOURCE_CUSTOM         hwPowerDown(TPD_POWER_SOURCE_CUSTOM, "TP");     #else         hwPowerDown(MT65XX_POWER_LDO_VGP2, "TP");     #endif         msleep(30);

    // Power on TP     #ifdef TPD_POWER_SOURCE_CUSTOM         hwPowerOn(TPD_POWER_SOURCE_CUSTOM, VOL_2800, "TP");     #else         hwPowerOn(MT65XX_POWER_LDO_VGP2, VOL_2800, "TP");     #endif         msleep(30);

#endif

    for (i = 0; i < 5; i++)     {     #if GTP_COMPATIBLE_MODE         if (CHIP_TYPE_GT9F == gtp_chip_type)         {             ret = gup_fw_download_proc(NULL, GTP_FL_ESD_RECOVERY);             if(FAIL == ret)             {                 GTP_ERROR("[force_reset_guitar]Check & repair fw failed.");                 continue;             }             //startup fw             ret = gtp_fw_startup(i2c_client_point);             if(FAIL == ret)             {                 GTP_ERROR("[force_reset_guitar]Startup fw failed.");                 continue;             }             break;         }         else     #endif         {             //Reset Guitar             gtp_reset_guitar(i2c_client_point, 20);             msleep(50);             //Send config             ret = gtp_send_cfg(i2c_client_point);                 if (ret < 0)             {                 continue;             }         }         break;     }     //mt65xx_eint_unmask(CUST_EINT_TOUCH_PANEL_NUM);     gtp_irq_enable();         if (i >= 5)     {         GTP_ERROR("Failed to reset guitar.");         return;     }     GTP_INFO("Esd recovery successful");     return; } #endif

#if GTP_ESD_PROTECT static s32 gtp_init_ext_watchdog(struct i2c_client *client) {     u8 opr_buffer[2] = {0xAA};     GTP_DEBUG("Init external watchdog.");     return i2c_write_bytes(client, 0x8041, opr_buffer, 1); }

void gtp_esd_switch(struct i2c_client *client, s32 on) {     spin_lock(&esd_lock);         if (SWITCH_ON == on)     // switch on esd     {         if (!esd_running)         {             esd_running = 1;             spin_unlock(&esd_lock);             GTP_INFO("Esd started");             queue_delayed_work(gtp_esd_check_workqueue, &gtp_esd_check_work, clk_tick_cnt);         }         else         {             spin_unlock(&esd_lock);         }     }     else    // switch off esd     {         if (esd_running)         {             esd_running = 0;             spin_unlock(&esd_lock);             GTP_INFO("Esd cancelled");             cancel_delayed_work_sync(&gtp_esd_check_work);         }         else         {             spin_unlock(&esd_lock);         }     } }

static void gtp_esd_check_func(struct work_struct *work) {     s32 i = 0;     s32 ret = -1;     u8 esd_buf[3] = {0x00};     if ((tpd_halt) || (gtp_loading_fw))     {         GTP_INFO("Esd suspended or IC update firmware!");         return;     }     for (i = 0; i < 3; i++)     {         ret = i2c_read_bytes_non_dma(i2c_client_point, 0x8040, esd_buf, 2);                 GTP_DEBUG("[Esd]0x8040 = 0x%02X, 0x8041 = 0x%02X", esd_buf[0], esd_buf[1]);         if (ret < 0)         {             // IIC communication problem             continue;         }         else         {             if ((esd_buf[0] == 0xAA) || (esd_buf[1] != 0xAA))             {                 u8 chk_buf[2] = {0x00};                 i2c_read_bytes_non_dma(i2c_client_point, 0x8040, chk_buf, 2);                                 GTP_DEBUG("[Check]0x8040 = 0x%02X, 0x8041 = 0x%02X", chk_buf[0], chk_buf[1]);                                 if ( (chk_buf[0] == 0xAA) || (chk_buf[1] != 0xAA) )                 {                     i = 3;          // jump to reset guitar                     break;                 }                 else                 {                     continue;                 }             }             else             {                 // IC works normally, Write 0x8040 0xAA, feed the watchdog                 esd_buf[0] = 0xAA;                 i2c_write_bytes_non_dma(i2c_client_point, 0x8040, esd_buf, 1);                                 break;             }         }     }

    if (i >= 3)     {       #if GTP_COMPATIBLE_MODE         if ((CHIP_TYPE_GT9F == gtp_chip_type) && (1 == rqst_processing))         {             GTP_INFO("Request Processing, no reset guitar.");         }         else     #endif         {             GTP_INFO("IC works abnormally! Process reset guitar.");             esd_buf[0] = 0x01;             esd_buf[1] = 0x01;             esd_buf[2] = 0x01;             i2c_write_bytes(i2c_client_point, 0x4226, esd_buf, 3);              msleep(50);             force_reset_guitar();         }     }

    if (!tpd_halt)     {         queue_delayed_work(gtp_esd_check_workqueue, &gtp_esd_check_work, clk_tick_cnt);     }     else     {         GTP_INFO("Esd suspended!");     }

    return; } #endif

static void tpd_down(s32 x, s32 y, s32 size, s32 id) {     if ((!size) && (!id))     {         input_report_abs(tpd->dev, ABS_MT_PRESSURE, 100);         input_report_abs(tpd->dev, ABS_MT_TOUCH_MAJOR, 100);     }     else     {         input_report_abs(tpd->dev, ABS_MT_PRESSURE, size);         input_report_abs(tpd->dev, ABS_MT_TOUCH_MAJOR, size);         /* track id Start 0 */         input_report_abs(tpd->dev, ABS_MT_TRACKING_ID, id);     }

    input_report_key(tpd->dev, BTN_TOUCH, 1);     input_report_abs(tpd->dev, ABS_MT_POSITION_X, x);     input_report_abs(tpd->dev, ABS_MT_POSITION_Y, y);     input_mt_sync(tpd->dev);     TPD_EM_PRINT(x, y, x, y, id, 1);

#if (defined(MT6575)||defined(MT6577))

    if (FACTORY_BOOT == get_boot_mode() || RECOVERY_BOOT == get_boot_mode())     {         tpd_button(x, y, 1);     }

#endif }

static void tpd_up(s32 x, s32 y, s32 id) {     input_report_key(tpd->dev, BTN_TOUCH, 0);     input_mt_sync(tpd->dev);     TPD_EM_PRINT(x, y, x, y, id, 0);

#if (defined(MT6575) || defined(MT6577))

    if (FACTORY_BOOT == get_boot_mode() || RECOVERY_BOOT == get_boot_mode())     {         tpd_button(x, y, 0);     }

#endif } #if GTP_CHARGER_SWITCH static void gtp_charger_switch(s32 dir_update) {     u32 chr_status = 0;     u8 chr_cmd[3] = {0x80, 0x40};     static u8 chr_pluggedin = 0;     int ret = 0;     #ifdef MT6573     chr_status = *(volatile u32 *)CHR_CON0;     chr_status &= (1 << 13); #else   // ( defined(MT6575) || defined(MT6577) || defined(MT6589) )     chr_status = upmu_is_chr_det(); #endif         if (chr_status)     // charger plugged in     {         if (!chr_pluggedin || dir_update)         {             chr_cmd[2] = 6;             ret = gtp_i2c_write(i2c_client_point, chr_cmd, 3);             if (ret > 0)             {                 GTP_INFO("Update status for Charger Plugin");     if (gtp_send_chr_cfg(i2c_client_point) < 0) {      GTP_ERROR("Send charger config failed.");     } else {      GTP_DEBUG("Send charger config.");     }             }             chr_pluggedin = 1;         }     }     else            // charger plugged out     {         if (chr_pluggedin || dir_update)         {             chr_cmd[2] = 7;             ret = gtp_i2c_write(i2c_client_point, chr_cmd, 3);             if (ret > 0)             {                 GTP_INFO("Update status for Charger Plugout");     if (gtp_send_cfg(i2c_client_point) < 0) {      GTP_ERROR("Send normal config failed.");     } else {      GTP_DEBUG("Send normal config.");     }             }             chr_pluggedin = 0;         }     } } #endif

static int touch_event_handler(void *unused) {     struct sched_param param = { .sched_priority = RTPM_PRIO_TPD };     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 u8 pre_touch = 0;     static u8 pre_key = 0; #if GTP_WITH_PEN     u8 pen_active = 0;     static u8 pre_pen = 0; #endif     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;     #if GTP_COMPATIBLE_MODE     u8  rqst_data[3] = {(u8)(GTP_REG_RQST >> 8), (u8)(GTP_REG_RQST & 0xFF), 0}; #endif

#ifdef TPD_PROXIMITY     s32 err = 0;     hwm_sensor_data sensor_data;     u8 proximity_status; #endif

#if GTP_GESTURE_WAKEUP     u8 doze_buf[3] = {0x81, 0x4B}; #endif

    sched_setscheduler(current, SCHED_RR, &param);     do     {         set_current_state(TASK_INTERRUPTIBLE);                 while (tpd_halt)         {         #if GTP_GESTURE_WAKEUP             if (DOZE_ENABLED == doze_status)             {                 break;             }         #endif             tpd_flag = 0;             msleep(20);         }

        wait_event_interruptible(waiter, tpd_flag != 0);         tpd_flag = 0;         TPD_DEBUG_SET_TIME;         set_current_state(TASK_RUNNING);

    #if GTP_CHARGER_SWITCH         gtp_charger_switch(0);     #endif

    #if GTP_GESTURE_WAKEUP         if (DOZE_ENABLED == doze_status)         {           if(p_gesture_control == 0)     {             ret = gtp_i2c_read(i2c_client_point, doze_buf, 3);             GTP_DEBUG("0x814B = 0x%02X", doze_buf[2]);             if (ret > 0)             {                              // if ((doze_buf[2] == 'a') || (doze_buf[2] == 'b') || (doze_buf[2] == 'c') ||                //     (doze_buf[2] == 'd') || (doze_buf[2] == 'e') || (doze_buf[2] == 'g') ||                //     (doze_buf[2] == 'h') || (doze_buf[2] == 'm') || (doze_buf[2] == 'o') ||                //     (doze_buf[2] == 'q') || (doze_buf[2] == 's') || (doze_buf[2] == 'v') ||               //      (doze_buf[2] == 'w') || (doze_buf[2] == 'y') || (doze_buf[2] == 'z') ||               //      (doze_buf[2] == 0x5E) /* ^ */|| (doze_buf[2] == 0x3E)/* > */              //       )              /*                 {                     if (doze_buf[2] != 0x5E)                     {                         GTP_INFO("Wakeup by gesture(%c), light up the screen!", doze_buf[2]);                     }                     else                     {                         GTP_INFO("Wakeup by gesture(^), light up the screen!");                     }                     doze_status = DOZE_WAKEUP;                     input_report_key(tpd->dev, KEY_POWER, 1);                     input_sync(tpd->dev);                     input_report_key(tpd->dev, KEY_POWER, 0);                     input_sync(tpd->dev);                     // clear 0x814B                     doze_buf[2] = 0x00;                     gtp_i2c_write(i2c_client_point, doze_buf, 3);                 }                 */                 if ((doze_buf[2] == 'c') || (doze_buf[2] == 'e') || (doze_buf[2] == 'm') ||    (doze_buf[2] == 'o') || (doze_buf[2] == 's') || (doze_buf[2] == 'v') ||                     (doze_buf[2] == 'w') || (doze_buf[2] == 'z')                     )                 {                  if (((doze_buf[2] == 'v') && ((gesture_three_byte_three & 0x01) == 0x01)) ||         ((doze_buf[2] == 'c') && ((gesture_three_byte_three & 0x02) == 0x02)) ||         ((doze_buf[2] == 'e') && ((gesture_three_byte_three & 0x04) == 0x04)) ||         ((doze_buf[2] == 'w') && ((gesture_three_byte_three & 0x08) == 0x08)) ||         ((doze_buf[2] == 'm') && ((gesture_three_byte_three & 0x10) == 0x10)) ||         ((doze_buf[2] == 's') && ((gesture_three_byte_three & 0x20) == 0x20)) ||         ((doze_buf[2] == 'z') && ((gesture_three_byte_three & 0x40) == 0x40)) ||                           ((doze_buf[2] == 'o') && ((gesture_three_byte_three & 0x80) == 0x80))                     )                  {                      GTP_INFO("Wakeup by gesture(%c), light up the screen!", doze_buf[2]);        doze_status = DOZE_WAKEUP;                         input_report_key(tpd->dev, KEY_GESTURE, 1);                         input_sync(tpd->dev);                         input_report_key(tpd->dev, KEY_GESTURE, 0);                         input_sync(tpd->dev);

                        if(doze_buf[2] == 'v')        {            gesture_data = 0xC6;        }        else if(doze_buf[2] == 'c')        {            gesture_data = 0xC1;        }        else if(doze_buf[2] == 'e')        {            gesture_data = 0xC0;        }        else if(doze_buf[2] == 'w')        {            gesture_data = 0xC2;        }        else if(doze_buf[2] == 'm')        {            gesture_data = 0xC3;        }        else if(doze_buf[2] == 's')        {            gesture_data = 0xC5;        }        else if(doze_buf[2] == 'z')        {            gesture_data = 0xCA;        }        else  //doze_buf[2] == 'o'        {            gesture_data = 0xC4;        }                                // clear 0x814B                         doze_buf[2] = 0x00;                         gtp_i2c_write(i2c_client_point, doze_buf, 3);

       gtp_enter_doze(i2c_client_point);                  }    else    {        // clear 0x814B                         doze_buf[2] = 0x00;                         gtp_i2c_write(i2c_client_point, doze_buf, 3);                         gtp_enter_doze(i2c_client_point);    }                 }                 else if ( (doze_buf[2] == 0xAA) || (doze_buf[2] == 0xBB) ||                     (doze_buf[2] == 0xAB) || (doze_buf[2] == 0xBA) )                 {                     char *direction[4] = {"Right", "Down", "Up", "Left"};                     u8 type = ((doze_buf[2] & 0x0F) - 0x0A) + (((doze_buf[2] >> 4) & 0x0F) - 0x0A) * 2;    if(((type == 0) && ((gesture_three_byte_four & 0x01) == 0x01)) ||     ((type == 1) && ((gesture_three_byte_four & 0x04) == 0x04)) ||     ((type == 2) && ((gesture_three_byte_four & 0x08) == 0x08)) ||     ((type == 3) && ((gesture_three_byte_four & 0x02) ==0x02))    )    {                         GTP_INFO("%s slide to light up the screen!", direction[type]);                         doze_status = DOZE_WAKEUP;                         input_report_key(tpd->dev, KEY_GESTURE, 1);                         input_sync(tpd->dev);                         input_report_key(tpd->dev, KEY_GESTURE, 0);                         input_sync(tpd->dev);                         // clear 0x814B                         doze_buf[2] = 0x00;                         gtp_i2c_write(i2c_client_point, doze_buf, 3);        if(type == 0)        {          gesture_data = 0xB1;        }        else if(type == 1)        {            gesture_data = 0xB3;        }        else if(type == 2)        {            gesture_data = 0xB2;        }        else   //type==3        {            gesture_data = 0xB0;        }

       gtp_enter_doze(i2c_client_point);           }    else    {        // clear 0x814B                         doze_buf[2] = 0x00;                         gtp_i2c_write(i2c_client_point, doze_buf, 3);                         gtp_enter_doze(i2c_client_point);     }                 }                 else if (0xCC == doze_buf[2])                 {                  if((gesture_three_byte_two & 0x01)== 0x01)                  {                          GTP_INFO("Double click to light up the screen!");                          doze_status = DOZE_WAKEUP;                         input_report_key(tpd->dev, KEY_GESTURE, 1);                          input_sync(tpd->dev);                          input_report_key(tpd->dev, KEY_GESTURE, 0);                          input_sync(tpd->dev);                          // clear 0x814B                          doze_buf[2] = 0x00;                          gtp_i2c_write(i2c_client_point, doze_buf, 3);               gesture_data = DOUBLE_TAP;

       gtp_enter_doze(i2c_client_point);                  }    else    {        // clear 0x814B                         doze_buf[2] = 0x00;                         gtp_i2c_write(i2c_client_point, doze_buf, 3);                         gtp_enter_doze(i2c_client_point);    }                 }                 else                 {                     // clear 0x814B                     doze_buf[2] = 0x00;                     gtp_i2c_write(i2c_client_point, doze_buf, 3);                     gtp_enter_doze(i2c_client_point);                 }             }             continue;         }  else  {   // clear 0x814B              doze_buf[2] = 0x00;              gtp_i2c_write(i2c_client_point, doze_buf, 3);              gtp_enter_doze(i2c_client_point);  }  }     #endif         ret = gtp_i2c_read(i2c_client_point, point_data, 12);         if (ret < 0)         {             GTP_ERROR("I2C transfer error. errno:%d\n ", ret);             continue;         }         finger = point_data[GTP_ADDR_LENGTH];             #if GTP_COMPATIBLE_MODE         if ((finger == 0x00) && (CHIP_TYPE_GT9F == gtp_chip_type))         {             ret = gtp_i2c_read(i2c_client_point, rqst_data, 3);

            if(ret < 0)             {                 GTP_ERROR("I2C transfer error. errno:%d\n ", ret);                 continue;             }             switch (rqst_data[2])             {                 case GTP_RQST_BAK_REF:                     GTP_INFO("Request Ref.");                     rqst_processing = 1;                     ret = gtp_bak_ref_proc(i2c_client_point, GTP_BAK_REF_SEND);                     if(SUCCESS == ret)                     {                         GTP_INFO("Send ref success.");                         rqst_data[2] = GTP_RQST_RESPONDED;                         gtp_i2c_write(i2c_client_point, rqst_data, 3);                         rqst_processing = 0;                     }                     goto exit_work_func;                                     case GTP_RQST_CONFIG:                     GTP_INFO("Request Config.");                     ret = gtp_send_cfg(i2c_client_point);                     if (ret < 0)                     {                         GTP_ERROR("Send config error.");                     }                     else                     {                         GTP_INFO("Send config success.");                         rqst_data[2] = GTP_RQST_RESPONDED;                         gtp_i2c_write(i2c_client_point, rqst_data, 3);                     }                     goto exit_work_func;                                     case GTP_RQST_MAIN_CLOCK:                     GTP_INFO("Request main clock.");                     rqst_processing = 1;                     ret = gtp_main_clk_proc(i2c_client_point);                     if(SUCCESS == ret)                     {                         GTP_INFO("Send main clk success.");                                                 rqst_data[2] = GTP_RQST_RESPONDED;                         gtp_i2c_write(i2c_client_point, rqst_data, 3);                         rqst_processing = 0;                     }                     goto exit_work_func;                                     case GTP_RQST_RESET:                     GTP_INFO("Request Reset.");                     gtp_recovery_reset(i2c_client_point);                     goto exit_work_func;                                     default:                     GTP_INFO("Undefined request code: 0x%02X", rqst_data[2]);                     rqst_data[2] = GTP_RQST_RESPONDED;                     gtp_i2c_write(i2c_client_point, rqst_data, 3);                     break;             }         }     #endif             if (finger == 0x00)         {             continue;         }                 if ((finger & 0x80) == 0)         {             goto exit_work_func;         }             #ifdef TPD_PROXIMITY         if (tpd_proximity_flag == 1)         {             proximity_status = point_data[GTP_ADDR_LENGTH];             GTP_DEBUG("REG INDEX[0x814E]:0x%02X\n", proximity_status);

            if (proximity_status & 0x60)                //proximity or large touch detect,enable hwm_sensor.             {                 tpd_proximity_detect = 0;                 //sensor_data.values[0] = 0;             }             else             {                 tpd_proximity_detect = 1;                 //sensor_data.values[0] = 1;             }

            //get raw data             GTP_DEBUG(" ps change\n");             GTP_DEBUG("PROXIMITY STATUS:0x%02X\n", tpd_proximity_detect);             //map and store data to hwm_sensor_data             sensor_data.values[0] = tpd_get_ps_value();             sensor_data.value_divide = 1;             sensor_data.status = SENSOR_STATUS_ACCURACY_MEDIUM;             //report to the up-layer             ret = hwmsen_get_interrupt_data(ID_PROXIMITY, &sensor_data);

            if (ret)             {                 GTP_ERROR("Call hwmsen_get_interrupt_data fail = %d\n", err);             }         }

    #endif

        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(i2c_client_point, buf, 2 + 8 * (touch_num - 1));             memcpy(&point_data[12], &buf[2], 8 * (touch_num - 1));         }

    #if (GTP_HAVE_TOUCH_KEY || GTP_PEN_HAVE_BUTTON)         key_value = point_data[3 + 8 * touch_num];

        if (key_value || pre_key)         {         #if GTP_PEN_HAVE_BUTTON             if (key_value == 0x40)             {                 GTP_DEBUG("BTN_STYLUS & BTN_STYLUS2 Down.");                 input_report_key(pen_dev, BTN_STYLUS, 1);                 input_report_key(pen_dev, BTN_STYLUS2, 1);                 pen_active = 1;             }             else if (key_value == 0x10)             {                 GTP_DEBUG("BTN_STYLUS Down, BTN_STYLUS2 Up.");                 input_report_key(pen_dev, BTN_STYLUS, 1);                 input_report_key(pen_dev, BTN_STYLUS2, 0);                 pen_active = 1;             }             else if (key_value == 0x20)             {                 GTP_DEBUG("BTN_STYLUS Up, BTN_STYLUS2 Down.");                 input_report_key(pen_dev, BTN_STYLUS, 0);                 input_report_key(pen_dev, BTN_STYLUS2, 1);                 pen_active = 1;             }             else             {                 GTP_DEBUG("BTN_STYLUS & BTN_STYLUS2 Up.");                 input_report_key(pen_dev, BTN_STYLUS, 0);                 input_report_key(pen_dev, BTN_STYLUS2, 0);                 if ( (pre_key == 0x40) || (pre_key == 0x20) ||                      (pre_key == 0x10)                    )                 {                     pen_active = 1;                 }             }             if (pen_active)             {                 touch_num = 0;      // shield pen point                 //pre_touch = 0;    // clear last pen status             }         #endif         #if GTP_HAVE_TOUCH_KEY             if (!pre_touch)             {                 for (i = 0; i < GTP_MAX_KEY_NUM; i++)                 {                     input_report_key(tpd->dev, touch_key_array[i], key_value & (0x01 << i));                 }                 touch_num = 0;  // shiled fingers             }         #endif         }     #endif         pre_key = key_value;

        GTP_DEBUG("pre_touch:%02x, finger:%02x.", pre_touch, finger);                 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;

                input_x = TPD_WARP_X(abs_x_max, input_x);                 input_y = TPD_WARP_Y(abs_y_max, input_y);

            #if GTP_WITH_PEN                 id = coor_data[0];                 if ((id & 0x80))      // pen/stylus is activated                 {                     GTP_DEBUG("Pen touch DOWN!");                     pre_pen = 1;                     //id &= 0x7F;                     id = 0;                     GTP_DEBUG("(%d)(%d, %d)[%d]", id, input_x, input_y, input_w);                     gtp_pen_down(input_x, input_y, input_w, id);                     pen_active = 1;                 }                 else             #endif                 {                     GTP_DEBUG(" (%d)(%d, %d)[%d]", id, input_x, input_y, input_w);                     tpd_down(input_x, input_y, input_w, id);                 }             }         }         else         {             if (pre_touch)             {             #if GTP_WITH_PEN                 if (pre_pen)                 {                       GTP_DEBUG("Pen touch UP!");                     gtp_pen_up();                     pre_pen = 0;                     pen_active = 1;                 }                 else             #endif                 {                     GTP_DEBUG("Touch Release!");                     tpd_up(0, 0, 0);                 }             }         }         pre_touch = touch_num;       #if GTP_WITH_PEN         if (pen_active)         {             pen_active = 0;             input_sync(pen_dev);         }         else     #endif         {             input_sync(tpd->dev);         }

exit_work_func:

        if (!gtp_rawdiff_mode)         {             ret = gtp_i2c_write(i2c_client_point, end_cmd, 3);

            if (ret < 0)             {                 GTP_INFO("I2C write end_cmd  error!");             }         }

    } while (!kthread_should_stop());

    return 0; }

static int tpd_local_init(void) {   #ifdef TPD_POWER_SOURCE_CUSTOM #ifdef CONFIG_OF_TOUCH #ifdef CONFIG_ARCH_MT6580  tpd->reg=regulator_get(tpd->tpd_dev,TPD_POWER_SOURCE_CUSTOM); // get pointer to regulator structure  if (IS_ERR(tpd->reg)) {   GTP_ERROR("regulator_get() failed!\n");  } #endif #endif #endif   #if GTP_ESD_PROTECT     clk_tick_cnt = 2 * HZ;   // HZ: clock ticks in 1 second generated by system     GTP_DEBUG("Clock ticks for an esd cycle: %d", clk_tick_cnt);     INIT_DELAYED_WORK(&gtp_esd_check_work, gtp_esd_check_func);     gtp_esd_check_workqueue = create_workqueue("gtp_esd_check");     spin_lock_init(&esd_lock);          // 2.6.39 & later     // esd_lock = SPIN_LOCK_UNLOCKED;   // 2.6.39 & before #endif

#if GTP_SUPPORT_I2C_DMA     tpd->dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);     gpDMABuf_va = (u8 *)dma_alloc_coherent(&tpd->dev->dev, GTP_DMA_MAX_TRANSACTION_LENGTH, &gpDMABuf_pa, GFP_KERNEL);     if(!gpDMABuf_va){         GTP_INFO("[Error] Allocate DMA I2C Buffer failed!\n");     }     memset(gpDMABuf_va, 0, GTP_DMA_MAX_TRANSACTION_LENGTH); #endif     if (i2c_add_driver(&tpd_i2c_driver) != 0)     {         GTP_INFO("unable to add i2c driver.\n");         return -1;     }

    if (tpd_load_status == 0) //if(tpd_load_status == 0) // disable auto load touch driver for linux3.0 porting     {         GTP_INFO("add error touch panel driver.\n");         i2c_del_driver(&tpd_i2c_driver);         return -1;     }

#ifdef TPD_HAVE_BUTTON     tpd_button_setting(TPD_KEY_COUNT, tpd_keys_local, tpd_keys_dim_local);// initialize tpd button data #endif

#if (defined(TPD_WARP_START) && defined(TPD_WARP_END))     TPD_DO_WARP = 1;     memcpy(tpd_wb_start, tpd_wb_start_local, TPD_WARP_CNT * 4);     memcpy(tpd_wb_end, tpd_wb_start_local, TPD_WARP_CNT * 4); #endif

#if (defined(TPD_HAVE_CALIBRATION) && !defined(TPD_CUSTOM_CALIBRATION))     memcpy(tpd_calmat, tpd_def_calmat_local, 8 * 4);     memcpy(tpd_def_calmat, tpd_def_calmat_local, 8 * 4); #endif

    // set vendor string     tpd->dev->id.vendor = 0x00;     tpd->dev->id.product = tpd_info.pid;     tpd->dev->id.version = tpd_info.vid;

    GTP_INFO("end %s, %d\n", __FUNCTION__, __LINE__);     tpd_type_cap = 1;

    return 0; }

static s8 gtp_enter_doze(struct i2c_client *client) {     s8 ret = -1;     s8 retry = 0;     u8 i2c_control_buf[3] = {(u8)(GTP_REG_SLEEP >> 8), (u8)GTP_REG_SLEEP, 8};

    GTP_DEBUG_FUNC();

    GTP_DEBUG("Entering gesture mode...");     while(retry++ < 5)     {         i2c_control_buf[0] = 0x80;         i2c_control_buf[1] = 0x46;         ret = gtp_i2c_write(client, i2c_control_buf, 3);         if (ret < 0)         {             GTP_DEBUG("Failed to set gesture flag into 0x8046, %d", retry);             continue;         }         i2c_control_buf[0] = 0x80;         i2c_control_buf[1] = 0x40;         ret = gtp_i2c_write(client, i2c_control_buf, 3);         if (ret > 0)         {             doze_status = DOZE_ENABLED;             GTP_INFO("Gesture mode enabled.");             return ret;         }         msleep(10);     }     GTP_ERROR("GTP send gesture cmd failed.");     return ret; }

/******************************************************* Function:     Eter sleep function.

Input:     client:i2c_client.

Output:     Executive outcomes.0--success,non-0--fail. *******************************************************/ static s8 gtp_enter_sleep(struct i2c_client *client) { #if GTP_COMPATIBLE_MODE     if (CHIP_TYPE_GT9F == gtp_chip_type)     {         u8 i2c_status_buf[3] = {0x80, 0x44, 0x00};         s32 ret = 0;               ret = gtp_i2c_read(client, i2c_status_buf, 3);         if(ret <= 0)         {              GTP_ERROR("[gtp_enter_sleep]Read ref status reg error.");         }                 if (i2c_status_buf[2] & 0x80)         {             //Store bak ref             ret = gtp_bak_ref_proc(client, GTP_BAK_REF_STORE);             if(FAIL == ret)             {                 GTP_ERROR("[gtp_enter_sleep]Store bak ref failed.");             }                }     } #endif #if GTP_POWER_CTRL_SLEEP

    GTP_GPIO_OUTPUT(GTP_RST_PORT, 0);       GTP_GPIO_OUTPUT(GTP_INT_PORT, 0);     msleep(10);

#ifdef MT6573     mt_set_gpio_mode(GPIO_CTP_EN_PIN, GPIO_CTP_EN_PIN_M_GPIO);     mt_set_gpio_dir(GPIO_CTP_EN_PIN, GPIO_DIR_OUT);     mt_set_gpio_out(GPIO_CTP_EN_PIN, GPIO_OUT_ZERO);      msleep(30); #else               // ( defined(MT6575) || defined(MT6577) || defined(MT6589) )

    #ifdef TPD_POWER_SOURCE_1800         hwPowerDown(TPD_POWER_SOURCE_1800, "TP");     #endif         #ifdef TPD_POWER_SOURCE_CUSTOM         hwPowerDown(TPD_POWER_SOURCE_CUSTOM, "TP");     #else         hwPowerDown(MT65XX_POWER_LDO_VGP2, "TP");     #endif #endif        GTP_INFO("GTP enter sleep by poweroff!");     return 0;     #else     {         s8 ret = -1;         s8 retry = 0;         u8 i2c_control_buf[3] = {(u8)(GTP_REG_SLEEP >> 8), (u8)GTP_REG_SLEEP, 5};                         GTP_GPIO_OUTPUT(GTP_INT_PORT, 0);         msleep(5);             while (retry++ < 5)         {             ret = gtp_i2c_write(client, i2c_control_buf, 3);                 if (ret > 0)             {                 GTP_INFO("GTP enter sleep!");                                     return ret;             }                 msleep(10);         }             GTP_ERROR("GTP send sleep cmd failed.");         return ret;     } #endif }

/******************************************************* Function:     Wakeup from sleep mode Function.

Input:     client:i2c_client.

Output:     Executive outcomes.0--success,non-0--fail. *******************************************************/ static s8 gtp_wakeup_sleep(struct i2c_client *client) {     u8 retry = 0;     s8 ret = -1;

    GTP_DEBUG("GTP wakeup begin.");

#if (GTP_POWER_CTRL_SLEEP)  

#if GTP_COMPATIBLE_MODE     if (CHIP_TYPE_GT9F == gtp_chip_type)     {         force_reset_guitar();         GTP_INFO("Esd recovery wakeup.");         return 0;     } #endif

    while (retry++ < 5)     {         ret = tpd_power_on(client);

        if (ret < 0)         {             GTP_ERROR("I2C Power on ERROR!");             continue;         }         GTP_INFO("Ic wakeup by poweron");         return 0;     } #else

#if GTP_COMPATIBLE_MODE     if (CHIP_TYPE_GT9F == gtp_chip_type)     {         u8 opr_buf[2] = {0};                 while (retry++ < 10)         {             GTP_GPIO_OUTPUT(GTP_INT_PORT, 1);             msleep(5);                         ret = gtp_i2c_test(client);                 if (ret >= 0)             {                  // Hold ss51 & dsp                 opr_buf[0] = 0x0C;                 ret = i2c_write_bytes(client, 0x4180, opr_buf, 1);                 if (ret < 0)                 {                     GTP_DEBUG("Hold ss51 & dsp I2C error,retry:%d", retry);                     continue;                 }                                 // Confirm hold                 opr_buf[0] = 0x00;                 ret = i2c_read_bytes(client, 0x4180, opr_buf, 1);                 if (ret < 0)                 {                     GTP_DEBUG("confirm ss51 & dsp hold, I2C error,retry:%d", retry);                     continue;                 }                 if (0x0C != opr_buf[0])                 {                     GTP_DEBUG("ss51 & dsp not hold, val: %d, retry: %d", opr_buf[0], retry);                     continue;                 }                 GTP_DEBUG("ss51 & dsp has been hold");                                 ret = gtp_fw_startup(client);                 if (FAIL == ret)                 {                     GTP_ERROR("[gtp_wakeup_sleep]Startup fw failed.");                     continue;                 }                 GTP_INFO("flashless wakeup sleep success");                 return ret;             }             force_reset_guitar();             retry = 0;             break;         }         if (retry >= 10)         {             GTP_ERROR("wakeup retry timeout, process esd reset");             force_reset_guitar();         }         GTP_ERROR("GTP wakeup sleep failed.");         return ret;     } #endif     while (retry++ < 10)     {     #if GTP_GESTURE_WAKEUP   if((gesture_three_byte_one == 0) || ((gesture_three_byte_two == 0) && (gesture_three_byte_three == 0) && (gesture_three_byte_four == 0)))   {   GTP_GPIO_OUTPUT(GTP_INT_PORT, 1);          msleep(5);   }   else   {              if (DOZE_WAKEUP != doze_status)             {                 GTP_INFO("Powerkey wakeup.");             }             else             {                 GTP_INFO("Gesture wakeup.");             }             doze_status = DOZE_DISABLED;                     gtp_irq_disable();             //mt65xx_eint_mask(CUST_EINT_TOUCH_PANEL_NUM);             gtp_reset_guitar(client, 20);             //mt65xx_eint_unmask(CUST_EINT_TOUCH_PANEL_NUM);             gtp_irq_enable();   }     #else             GTP_GPIO_OUTPUT(GTP_INT_PORT, 1);         msleep(5);     #endif                 ret = gtp_i2c_test(client);

        if (ret >= 0)         {             GTP_INFO("GTP wakeup sleep.");         #if (!GTP_GESTURE_WAKEUP)             {                 gtp_int_sync(25);             #if GTP_ESD_PROTECT                 gtp_init_ext_watchdog(client);             #endif             }         #endif       if((gesture_three_byte_one == 0) || ((gesture_three_byte_two == 0) && (gesture_three_byte_three == 0) && (gesture_three_byte_four == 0)))       {        gtp_int_sync(25);                 #if GTP_ESD_PROTECT                     gtp_init_ext_watchdog(client);                 #endif       }                         return ret;         }         gtp_reset_guitar(client, 20);     } #endif     GTP_ERROR("GTP wakeup sleep failed.");     return ret; }

/* Function to manage low power suspend */ static void tpd_suspend(struct early_suspend *h) {     s32 ret = -1;

    GTP_INFO("System suspend.");

#ifdef TPD_PROXIMITY

    if (tpd_proximity_flag == 1)     {         return ;     }

#endif

    tpd_halt = 1; #if GTP_ESD_PROTECT     gtp_esd_switch(i2c_client_point, SWITCH_OFF); #endif     #if GTP_GESTURE_WAKEUP     if((gesture_three_byte_one == 0) || ((gesture_three_byte_two == 0) && (gesture_three_byte_three == 0) && (gesture_three_byte_four == 0)))     {         gtp_irq_disable();            ret = gtp_enter_sleep(i2c_client_point);     }     else    {  ret = gtp_enter_doze(i2c_client_point);     } #else        //mt65xx_eint_mask(CUST_EINT_TOUCH_PANEL_NUM);     gtp_irq_disable();         ret = gtp_enter_sleep(i2c_client_point); #endif     if (ret < 0)     {         GTP_ERROR("GTP early suspend failed.");     }     // to avoid waking up while not sleeping, delay 48 + 10ms to ensure reliability     msleep(58); }

/* Function to manage power-on resume */ static void tpd_resume(struct early_suspend *h) {     s32 ret = -1;

    GTP_INFO("System resume.");     #ifdef TPD_PROXIMITY

    if (tpd_proximity_flag == 1)     {         return ;     }

#endif     ret = gtp_wakeup_sleep(i2c_client_point);

    if (ret < 0)     {         GTP_ERROR("GTP later resume failed.");     }     #if GTP_COMPATIBLE_MODE     if (CHIP_TYPE_GT9F == gtp_chip_type)     {         // do nothing     }     else #endif     {         gtp_send_cfg(i2c_client_point);     }     #if GTP_CHARGER_SWITCH     gtp_charger_switch(1);  // force update #endif

    tpd_halt = 0; #if GTP_GESTURE_WAKEUP if((gesture_three_byte_one == 0) || ((gesture_three_byte_two == 0) && (gesture_three_byte_three == 0) && (gesture_three_byte_four == 0))) {  gtp_irq_enable(); } else {     doze_status = DOZE_DISABLED; } #else     //mt65xx_eint_unmask(CUST_EINT_TOUCH_PANEL_NUM);     gtp_irq_enable(); #endif

#if GTP_ESD_PROTECT     gtp_esd_switch(i2c_client_point, SWITCH_ON); #endif

}

static struct tpd_driver_t tpd_device_driver = {     .tpd_device_name = "gt9xx",     .tpd_local_init = tpd_local_init,     .suspend = tpd_suspend,     .resume = tpd_resume, #ifdef TPD_HAVE_BUTTON     .tpd_have_button = 1, #else     .tpd_have_button = 0, #endif };

/* called when loaded into kernel */ static int __init tpd_driver_init(void) {     GTP_INFO("MediaTek gt91xx touch panel driver init\n");

    i2c_register_board_info(I2C_BUS_NUMBER, &i2c_tpd, 1);     if (tpd_driver_add(&tpd_device_driver) < 0)         GTP_INFO("add generic driver failed\n");

    return 0; }

/* should never be called */ static void __exit tpd_driver_exit(void) {     GTP_INFO("MediaTek gt91xx touch panel driver exit\n");     tpd_driver_remove(&tpd_device_driver); #if GTP_COVER_CONTROL     unregister_cover_notifier(&cover_notifier1); #endif #if GTP_P_GESTURE_CONTROL     unregister_gesture_notifier(&gesture_notifier1); #endif }

module_init(tpd_driver_init); module_exit(tpd_driver_exit);

 

posted on 2015-12-29 15:43  乐学乐  阅读(938)  评论(0编辑  收藏  举报

导航