A33_lightsensor、距感驱动调试

lichee\tools\pack\chips\sun8iw5p1\configs\m86\sysconfig.fex里面
;--------------------------------------------------------------------------------
;light sensor
;--------------------------------------------------------------------------------
[ls_para]
ls_used             = 1
ls_twi_id           = 0 ;第0组I2C
ls_twi_addr         = 0x23
ls_int              = port:PB07<4><1><default><default> ; light sensor对应的中断脚

 

;----------------------------------------------------------------------------------
;i2c configuration
; twi_used = twix enable
;----------------------------------------------------------------------------------
[twi0]
twi_used        = 1 ;第0组I2C有使用,所以要为1
twi_scl         = port:PH02<2><default><default><default> ;第0组I2C 对应的GPIO脚
twi_sda         = port:PH03<2><default><default><default>
//----------------------------------------------------------------------------------
lichee/linux-3.4/drivers/input/misc/stk3420.c 源码如下

 

#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/i2c.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/device.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/leds.h>
#include <linux/gpio.h>
#include <linux/wakelock.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/workqueue.h>
#include <linux/uaccess.h>
#include <linux/module.h>
#include <linux/timer.h>
#include <linux/suspend.h>
#include <linux/init-input.h>
#include <mach/sys_config.h>
#ifdef CONFIG_SCENELOCK
#include <linux/power/scenelock.h>
#endif
#ifdef CONFIG_PM
#include <linux/pm.h>
#endif

 

#include <linux/gfp.h>

 

#define DRIVER_VERSION  "5.2.4"

 

/*********************************** Driver Settings ***********************************/
//#define QUALCOMM_PLATFORM
#define SPREADTRUM_PLATFORM

 

#define CONFIG_STK_PS_ALS_USE_CHANGE_THRESHOLD
#define STK_PS_INT_MODE   0 /* 0:normal interrupt; 1:LOW for near, HIGH for far */
#define STK_POLL_PS
#define STK_POLL_ALS  /* ALS interrupt is valid only when STK_PS_INT_MODE = 0 */
//#define CALI_PS_EVERY_TIME
//#define STK_ALS_FIR
//#define STK_IRS
//#define STK_CHK_REG
#define STK_6020_TEMP

 

/***********************************  Tunable Values ***********************************/
#ifdef CONFIG_STK_PS_ALS_USE_CHANGE_THRESHOLD
 #define STK_ALS_CHANGE_THD 10 /* The threshold to trigger ALS interrupt, unit: lux */
#endif

 

#define STK_MAX_MIN_DIFF 1000
#define STK_LT_N_CT  100
#define STK_HT_N_CT  300

 

/*********************************** Platform-specific Settings ***********************************/

 

#define STK3420_SLAVE_ADDR       0x58

 

/* Addresses to scan */
static const unsigned short normal_i2c[2] = {STK3420_SLAVE_ADDR,I2C_CLIENT_END};
static int i2c_num = 0;
static const unsigned short i2c_address[] = {STK3420_SLAVE_ADDR, STK3420_SLAVE_ADDR};

 

#ifdef SPREADTRUM_PLATFORM
 #include "stk3420.h"
#else
 #include "linux/stk3420.h"
#endif

 

/*********************************** Registers ***********************************/
/* Define Register Map */
#define STK_STATE_REG     0x00
#define STK_PS_GS_CTRL1_REG    0x01
#define STK_ALS_CTRL1_REG    0x02
#define STK_LED_CTRL_REG     0x03
#define STK_INT_REG      0x04
#define STK_WAIT1_PSGS_REG    0x05
#define STK_THDH1_PS_REG    0x06
#define STK_THDH2_PS_REG    0x07
#define STK_THDL1_PS_REG     0x08
#define STK_THDL2_PS_REG     0x09
#define STK_THDH1_ALS_REG    0x0A
#define STK_THDH2_ALS_REG    0x0B
#define STK_THDL1_ALS_REG    0x0C
#define STK_THDL2_ALS_REG    0x0D
#define STK_FLAG_REG      0x10
#define STK_DATA1_PS_REG     0x11
#define STK_DATA2_PS_REG     0x12
#define STK_DATA1_ALS_REG    0x13
#define STK_DATA2_ALS_REG    0x14
#define STK_DATA1_IRS_REG    0x17
#define STK_DATA2_IRS_REG    0x18
#define STK_ALS_CTRL2_REG    0x19
#define STK_WAIT_ALS_REG     0x1B
#define STK_WAIT2_PS_REG     0x1C
#define STK_PS_GS_CTRL2_REG    0x1D
#define STK_GS_FLAG_REG     0x1E
#define STK_GS_FIFO_CTRL_REG    0x1F
#define STK_DATA1_GSE_REG    0x20
#define STK_PDT_ID_REG     0x3E
#define STK_RSRVD_REG     0x3F
#define STK_SW_RESET_REG    0x80

 

/* Define state reg */
#define STK_STATE_EN_IRS_MASK   0x80
#define STK_STATE_EN_BGIR_MASK  0x40
#define STK_STATE_EN_ALS_RO_MASK  0x20
#define STK_STATE_EN_PS_RO_MASK  0x10
#define STK_STATE_EN_WAIT_ALS_MASK 0x08
#define STK_STATE_EN_WAIT_PSGS_MASK 0x04
#define STK_STATE_EN_ALS_MASK  0x02
#define STK_STATE_EN_PS_MASK   0x01

 

/* Define PS ctrl reg */
#define STK_PS_PRS_MASK   0xC0
#define STK_PS_GAIN_MASK   0x30
#define STK_PS_IT_MASK   0x0F

 

/* Define ALS ctrl reg */
#define STK_ALS_PRS_MASK  0xC0
#define STK_ALS_GAIN_MASK  0x30
#define STK_ALS_IT_MASK   0x0F

 

/* Define LED ctrl reg */
#define STK_LED_IRDR_MASK  0xC0
#define STK_LED_DT_MASK   0x3F

 

/* Define interrupt reg */
#define STK_INT_CTRL_MASK   0x80
#define STK_INT_GS_MASK   0x10
#define STK_INT_ALS_MASK   0x08
#define STK_INT_PS_MODE_MASK  0x02
#define STK_INT_PS_MASK   0x01

 


/* Define flag reg */
#define STK_FLG_ALSDR_MASK  0x80
#define STK_FLG_PSDR_MASK  0x40
#define STK_FLG_ALSINT_MASK  0x20
#define STK_FLG_PSINT_MASK  0x10
#define STK_FLG_GSINT_MASK  0x08
#define STK_FLG_IRFAIL_MASK  0x04
#define STK_FLG_IRSDR_MASK  0x02
#define STK_FLG_NF_MASK   0x01

 

/* Define gsflag reg */
#define STK_GSFLG_FIFO_LEN  0x1F
#define STK_GSFLG_FIFO_OV   0x80

 

/* Define psgs_ctrl2 reg */
#define STK_PSGS2_EN_NS   0x02
#define STK_PSGS2_EN_EW   0x01
/***********************************  Default Define ***********************************/

 

/* misc define */
#define STK_MIN_ALS_POLL_DELAY_NS 60000000
#define STK_DEF_ALS_POLL_DELAY_MS 120
#define STK_DEF_GES_POLL_DELAY_MS 60
#define STK_DEF_PS_POLL_DELAY_MS  60
#define STK_FAST_GES_POLL_DELAY_MS 30

 

#define STK_IRC_MAX_ALS_CODE  20000
#define STK_IRC_MIN_ALS_CODE  25
#define STK_IRC_MIN_IR_CODE  50
#define STK_IRC_ALS_DENOMI  2
#define STK_IRC_ALS_NUMERA  5
#define STK_IRC_ALS_CORREC  850

 

//#define DEVICE_NAME  "stk_ps" //TODO:  for old HAL
#define DEVICE_NAME "stk3420"
#define GES_NAME  "stk_gesture" //手势
#define DAE_NAME  "stk_dae"
//#define ALS_NAME  "stk3420-ls"
#define ALS_NAME "lightsensor-level" //光感
#define PS_NAME "proximity" //距感

 

 

 

#define STK_EN_GES_TOUCN 0x40

 

#define APS_FUN(f)               printk(KERN_INFO "%s\n", __FUNCTION__)
#define printk(fmt, args...)   pr_err( fmt, ##args)
#define APS_LOG(fmt, args...)    printk(fmt, ##args)
#define printk(fmt, args...)   printk(fmt, ##args)
#define APS_WARN(fmt, args...)   pr_warning(fmt, ##args)

 

#if 1
static struct sensor_config_info ls_sensor_info = {
 .input_type = LS_TYPE,
 .int_number = 0,
 .ldo = NULL,
};
#endif

 


#if 1

 

#ifdef SPREADTRUM_PLATFORM
//extern int sprd_3rdparty_gpio_pls_irq;

 

static struct stk3420_platform_data stk3420_pfdata= {
    .psgsctrl1_reg = 0x02,  
    .alsctrl1_reg = 0x33,
    .ledctrl_reg = 0x40,  
    .wait1_psgs_reg_ps = 0x3F,   
    .wait1_psgs_reg_gs = 0x6,   
 .alsctrl2_reg = 0x74,
 .wait_als_reg = 0x00,
 .wait2_ps_reg = 0x03,
 .fifoctrl_reg = 0x08,
 .psgsctrl2_reg = 0x00,
    .ps_thd_h =1700,
    .ps_thd_l = 1500,
 //.int_number = GPIOL(02),
    .transmittance = 10000,
 
};
#endif

 

#ifdef STK_ALS_FIR
#define STK_FIR_LEN 8
#define MAX_FIR_LEN 32

 

struct data_filter {
    u16 raw[MAX_FIR_LEN];
    int sum;
    int number;
    int idx;
};
#endif

 

struct stk3420_regs {
    uint8_t state_reg;
    uint8_t psgsctrl1_reg;
    uint8_t alsctrl1_reg;
    uint8_t ledctrl_reg;
 uint8_t wait1_psgs_reg_ps;
 uint8_t wait1_psgs_reg_gs;
 uint8_t alsctrl2_reg;
 uint8_t wait_als_reg;
 uint8_t wait2_ps_reg;
 uint8_t psgsctrl2_reg;
    uint8_t int_reg;
    uint8_t fifoctrl_reg; 
};

 

struct stk3420_tune0 {
    uint16_t psa;
    uint16_t psi;
    uint16_t psi_set;
    bool tune_zero_init_proc;
    uint32_t ps_stat_data[3];
    int data_count;
    int stk_max_min_diff;
    int stk_lt_n_ct;
    int stk_ht_n_ct;
};

 

struct stk3420_poll {
    struct work_struct work_str;
    struct hrtimer hr_timer;
    struct workqueue_struct *wq; 
    ktime_t poll_delay; 
};

 


struct stk3420_data {
    struct i2c_client *client;
    struct stk3420_platform_data *pdata;

 


#if (!defined(STK_POLL_PS) || !defined(STK_POLL_ALS))
    int32_t irq;
    struct work_struct stk_work;
    struct workqueue_struct *stk_wq;
#endif
    uint16_t ir_code;
    uint16_t als_correct_factor;
 struct stk3420_regs reg;
    int  int_number;
    uint16_t ps_thd_h;
    uint16_t ps_thd_l;
#ifdef CALI_PS_EVERY_TIME
    uint16_t ps_high_thd_boot;
    uint16_t ps_low_thd_boot;
#endif
    struct mutex io_lock;
    struct input_dev *ps_input_dev;
    int32_t ps_distance_last;
    bool ps_enabled;
    bool re_enable_ps;
    struct wake_lock ps_wakelock;
 struct stk3420_poll ps_poll;
#ifdef STK_POLL_PS
    struct wake_lock ps_nosuspend_wl;
#endif
    struct input_dev *als_input_dev;
    uint32_t als_lux_last;
    uint32_t als_transmittance;
    bool als_enabled;
    bool re_enable_als;
#ifdef STK_POLL_ALS
 struct stk3420_poll als_poll;
#endif
    bool first_boot;
 struct stk3420_tune0 tune0;
#ifdef STK_ALS_FIR
    struct data_filter      fir;
    atomic_t                firlength;
#endif
    atomic_t recv_reg;
    struct input_dev *ges_input_dev;
    int ges_enabled;
    int re_enable_ges;
    struct input_dev *dae_input_dev; 
 uint16_t ges_last_code[4];
#ifdef CONFIG_HAS_EARLYSUSPEND
    //struct early_suspend stk_early_suspend;
#endif
};

 

#if( !defined(CONFIG_STK_PS_ALS_USE_CHANGE_THRESHOLD))
static uint32_t lux_threshold_table[] = {
    3,
    10,
    40,
    65,
    145,
    300,
    550,
    930,
    1250,
    1700,
};

 

#define LUX_THD_TABLE_SIZE (sizeof(lux_threshold_table)/sizeof(uint32_t)+1)
static uint16_t code_threshold_table[LUX_THD_TABLE_SIZE+1];
#endif

 

static int32_t stk3420_enable_ps(struct stk3420_data *ps_data, uint8_t enable, uint8_t validate_reg);
static int32_t stk3420_enable_als(struct stk3420_data *ps_data, uint8_t enable);
static int32_t stk3420_set_ps_thd_l(struct stk3420_data *ps_data, uint16_t thd_l);
static int32_t stk3420_set_ps_thd_h(struct stk3420_data *ps_data, uint16_t thd_h);
static int32_t stk3420_set_als_thd_l(struct stk3420_data *ps_data, uint16_t thd_l);
static int32_t stk3420_set_als_thd_h(struct stk3420_data *ps_data, uint16_t thd_h);
#ifdef STK_IRS
static int32_t stk3420_get_ir_reading(struct stk3420_data *ps_data);
#endif
static int32_t stk3420_software_reset(struct stk3420_data *ps_data);
#ifdef STK_CHK_REG
static int stk3420_validate_n_handle(struct i2c_client *client);
#endif

 

static uint32_t stk3420_ps_report_distance(struct stk3420_data *ps_data, uint32_t ps_code, uint32_t nf_status);
static void stk3420_als_report_lux(struct stk3420_data *ps_data, uint32_t lux);
static uint32_t stk3420_alscode2lux(struct stk3420_data *ps_data, uint32_t alscode);
static void stk3420_als_set_new_thd(struct stk3420_data *ps_data, uint32_t alscode);
static uint32_t stk3420_get_lux_interval_index(uint16_t alscode);
static void stk3420_report_ges_code(struct stk3420_data *ps_data);

 


static int stk3420_i2c_read_data(struct i2c_client *client, unsigned char command, int length, unsigned char *values)
{
    uint8_t retry=0;
    int ret;
    struct i2c_msg msgs[] = {
        {
            .addr = client->addr,
            .flags = 0,
            .len = 1,
            .buf = &command,
        },
        {
            .addr = client->addr,
            .flags = I2C_M_RD,
            .len = length,
            .buf = values,
        },
    };

 

    for (retry = 0; retry < 5; retry++) {
        ret = i2c_transfer(client->adapter, msgs, 2);
        if (ret == 2)
            break;
        else
            mdelay(5);
    }
 printk("%s:i2c addr==0x%x,retry=%d,i2c_transfer return value==%d\n",__func__,client->addr,retry,ret);
    if (retry >= 5) {
        printk("%s: i2c read fail, ret=%d\n", __func__, ret);
        return -EIO;
    }
    return 0;
}

 

static int stk3420_i2c_write_data(struct i2c_client *client, unsigned char command, int length, unsigned char *values)
{
    int retry=0;
    int ret;
    unsigned char data[11];
    struct i2c_msg msg;
    int index;

 

    if (!client)
        return -EINVAL;
    else
        if (length >= 10) {
            printk("%s:length %d exceeds 10\n", __func__, length);
            return -EINVAL;
        }

 

    data[0] = command;
    for (index=1; index<=length; index++)
        data[index] = values[index-1];

 

    msg.addr = client->addr;
    msg.flags = 0;
    msg.len = length+1;
    msg.buf = data;

 

    for (retry = 0; retry < 5; retry++) {
        ret = i2c_transfer(client->adapter, &msg, 1);
        if (ret == 1)
            break;
        else
            mdelay(5);
    }

 

    if (retry >= 5) {
        printk("%s: i2c write fail, ret=%d\n", __func__, ret);
        return -EIO;
    }
    return 0;
}

 

static int stk3420_i2c_read_byte_data(struct i2c_client *client, unsigned char command)
{
    unsigned char value;
    int ret;
    ret = stk3420_i2c_read_data(client, command, 1, &value);
    if(ret < 0)
        return ret;
    return value;
}

 

static int stk3420_i2c_write_byte_data(struct i2c_client *client, unsigned char command, unsigned char value)
{
    int ret;
    ret = stk3420_i2c_write_data(client, command, 1, &value);
    return ret;
}

 


static int32_t stk3420_init_all_reg(struct stk3420_data *ps_data)
{
    int32_t ret;

 

 ret = stk3420_software_reset(ps_data);
 if(ret < 0)
  return ret; 
 
    ret = stk3420_i2c_write_byte_data(ps_data->client, STK_STATE_REG, ps_data->reg.state_reg);
    if (ret < 0) {
        printk("%s: write i2c error\n", __func__);
        return ret;
    }
    ret = stk3420_i2c_write_byte_data(ps_data->client, STK_PS_GS_CTRL1_REG, ps_data->reg.psgsctrl1_reg);
    if (ret < 0) {
        printk("%s: write i2c error\n", __func__);
        return ret;
    }
    ret = stk3420_i2c_write_byte_data(ps_data->client, STK_ALS_CTRL1_REG, ps_data->reg.alsctrl1_reg);
    if (ret < 0) {
        printk("%s: write i2c error\n", __func__);
        return ret;
    }
    ret = stk3420_i2c_write_byte_data(ps_data->client, STK_LED_CTRL_REG, ps_data->reg.ledctrl_reg);
    if (ret < 0) {
        printk("%s: write i2c error\n", __func__);
        return ret;
    }
    ret = stk3420_i2c_write_byte_data(ps_data->client, STK_WAIT1_PSGS_REG, ps_data->reg.wait1_psgs_reg_ps);
    if (ret < 0) {
        printk("%s: write i2c error\n", __func__);
        return ret;
    }
    ret = stk3420_i2c_write_byte_data(ps_data->client, STK_WAIT_ALS_REG, ps_data->reg.wait_als_reg);
    if (ret < 0) {
        printk("%s: write i2c error\n", __func__);
        return ret;
    }
    ret = stk3420_i2c_write_byte_data(ps_data->client, STK_WAIT2_PS_REG, ps_data->reg.wait2_ps_reg);
    if (ret < 0) {
        printk("%s: write i2c error\n", __func__);
        return ret;
    }
    ret = stk3420_i2c_write_byte_data(ps_data->client, STK_PS_GS_CTRL2_REG, ps_data->reg.psgsctrl2_reg);
    if (ret < 0) {
        printk("%s: write i2c error\n", __func__);
        return ret;
    }
    ret = stk3420_i2c_write_byte_data(ps_data->client, STK_INT_REG, ps_data->reg.int_reg);
    if (ret < 0) {
        printk("%s: write i2c error\n", __func__);
        return ret;
    } 
    ret = stk3420_i2c_write_byte_data(ps_data->client, STK_GS_FIFO_CTRL_REG, ps_data->reg.fifoctrl_reg);
    if (ret < 0) {
        printk("%s: write i2c error\n", __func__);
        return ret;
    }  
#ifdef STK_IRS 
    ret = stk3420_i2c_write_byte_data(ps_data->client, STK_ALS_CTRL2_REG, ps_data->reg.alsctrl2_reg);
    if (ret < 0) {
        printk("%s: write i2c error\n", __func__);
        return ret;
    }  
#endif
 
    ret = stk3420_i2c_write_byte_data(ps_data->client, 0x94, 0xC2);
    if (ret < 0) {
        printk("%s: write i2c error\n", __func__);
        return ret;
    }
 
#ifdef STK_6020_TEMP 
    ret = stk3420_i2c_write_byte_data(ps_data->client, 0x95, 0x90); // 200f
    if (ret < 0) {
        printk("%s: write i2c error\n", __func__);
        return ret;
    } 
#endif
 /*
    ret = stk3420_i2c_write_byte_data(ps_data->client, STK_LED_CTRL_REG, 0xC0); // 150 mA
    if (ret < 0) {
        printk("%s: write i2c error\n", __func__);
        return ret;
    } 
    ret = stk3420_i2c_write_byte_data(ps_data->client, 0x94, 0xC6); // 150 mA
    if (ret < 0) {
        printk("%s: write i2c error\n", __func__);
        return ret;
    }  
 */ 
 
    ps_data->tune0.psa = 0x0;
    ps_data->tune0.psi = 0xFFFF;
    stk3420_set_ps_thd_h(ps_data, ps_data->ps_thd_h);
    stk3420_set_ps_thd_l(ps_data, ps_data->ps_thd_l);
    return 0;
}

 


static int32_t stk3420_check_pid(struct stk3420_data *ps_data)
{
    unsigned char value[2];
    int ret;

 

    ret = stk3420_i2c_read_data(ps_data->client, STK_PDT_ID_REG, 2, &value[0]);
    if(ret < 0) {
        printk("%s: fail, ret=%d\n", __func__, ret);
        return ret;
    }
 printk("%s: PID=0x%x, RID=0x%x\n", __func__, value[0], value[1]);
/* 
 switch (value[0]) {
 case 0x50:
  
  break;
 default:  
  printk("%s: invalid pid\n", __func__);
  return -1;
 }
*/
    return 0;
}

 


static int32_t stk3420_software_reset(struct stk3420_data *ps_data)
{
    int32_t ret;
    uint8_t w_reg;

 

    w_reg = 0x7F;
    ret = stk3420_i2c_write_byte_data(ps_data->client,STK_WAIT1_PSGS_REG,w_reg);
    if (ret<0) {
        printk("%s: software reset: write i2c error, ret=%d\n", __func__, ret);
        return ret;
    }
    ret = stk3420_i2c_read_byte_data(ps_data->client,STK_WAIT1_PSGS_REG);
    if (w_reg != ret) {
        printk("%s: software reset: read-back value is not the same\n", __func__);
        return -1;
    }

 

    ret = stk3420_i2c_write_byte_data(ps_data->client,STK_SW_RESET_REG,0);
    if (ret<0) {
        printk("%s: software reset: read error after reset\n", __func__);
        return ret;
    }
    usleep_range(1000, 5000);
    return 0;
}

 

static int32_t stk3420_set_als_thd_l(struct stk3420_data *ps_data, uint16_t thd_l)
{
    unsigned char val[2];
    int ret;
    val[0] = (thd_l & 0xFF00) >> 8;
    val[1] = thd_l & 0x00FF;
    ret = stk3420_i2c_write_data(ps_data->client, STK_THDL1_ALS_REG, 2, val);
    if(ret < 0)
        printk("%s: fail, ret=%d\n", __func__, ret);
    return ret;
}
static int32_t stk3420_set_als_thd_h(struct stk3420_data *ps_data, uint16_t thd_h)
{
    unsigned char val[2];
    int ret;
    val[0] = (thd_h & 0xFF00) >> 8;
    val[1] = thd_h & 0x00FF;
    ret = stk3420_i2c_write_data(ps_data->client, STK_THDH1_ALS_REG, 2, val);
    if(ret < 0)
        printk("%s: fail, ret=%d\n", __func__, ret);
    return ret;
}

 

static int32_t stk3420_set_ps_thd_l(struct stk3420_data *ps_data, uint16_t thd_l)
{
    unsigned char val[2];
    int ret;
    val[0] = (thd_l & 0xFF00) >> 8;
    val[1] = thd_l & 0x00FF;
    ret = stk3420_i2c_write_data(ps_data->client, STK_THDL1_PS_REG, 2, val);
    if(ret < 0)
        printk("%s: fail, ret=%d\n", __func__, ret);
    return ret;
}
static int32_t stk3420_set_ps_thd_h(struct stk3420_data *ps_data, uint16_t thd_h)
{
    unsigned char val[2];
    int ret;
    val[0] = (thd_h & 0xFF00) >> 8;
    val[1] = thd_h & 0x00FF;
    ret = stk3420_i2c_write_data(ps_data->client, STK_THDH1_PS_REG, 2, val);
    if(ret < 0)
        printk("%s: fail, ret=%d\n", __func__, ret);
    return ret;
}

 

static int32_t stk3420_set_flag(struct stk3420_data *ps_data, uint8_t org_flag_reg, uint8_t clr)
{
    uint8_t w_flag;
    int ret;
 
    w_flag = org_flag_reg | (STK_FLG_ALSINT_MASK | STK_FLG_PSINT_MASK | STK_FLG_GSINT_MASK);
    w_flag &= (~clr);
    //printk("%s: org_flag_reg=0x%x, w_flag = 0x%x\n", __func__, org_flag_reg, w_flag);
    ret = stk3420_i2c_write_byte_data(ps_data->client,STK_FLAG_REG, w_flag);
    if(ret < 0)
        printk("%s: fail, ret=%d\n", __func__, ret);
    return ret;
}

 

static int32_t stk3420_get_flag(struct stk3420_data *ps_data)
{
    int ret;
    ret = stk3420_i2c_read_byte_data(ps_data->client,STK_FLAG_REG);
    if(ret < 0)
        printk("%s: fail, ret=%d\n", __func__, ret);
    return ret;
}

 

static int32_t stk3420_set_gsflag(struct stk3420_data *ps_data, uint8_t gsflag)
{
    int ret;

 

    ret = stk3420_i2c_write_byte_data(ps_data->client,STK_GS_FLAG_REG, gsflag);
    if(ret < 0)
        printk("%s: fail, ret=%d\n", __func__, ret);
    return ret;
}

 

static int32_t stk3420_get_gsflag(struct stk3420_data *ps_data)
{
    int ret;
    ret = stk3420_i2c_read_byte_data(ps_data->client,STK_GS_FLAG_REG);
    if(ret < 0)
        printk("%s: fail, ret=%d\n", __func__, ret);
    return ret;
}

 

static int32_t stk3420_set_state(struct stk3420_data *ps_data, uint8_t state)
{
    int ret;
    ret = stk3420_i2c_write_byte_data(ps_data->client,STK_STATE_REG, state);
    if(ret < 0)
        printk("%s: fail, ret=%d\n", __func__, ret);
    return ret;
}

 

static int32_t stk3420_get_state(struct stk3420_data *ps_data)
{
    int ret;
    ret = stk3420_i2c_read_byte_data(ps_data->client,STK_STATE_REG);
    if(ret < 0)
        printk("%s: fail, ret=%d\n", __func__, ret);
    return ret;
}

 

static int32_t stk3420_set_wait1_psgs(struct stk3420_data *ps_data, uint8_t wait1)
{
    int ret;
    ret = stk3420_i2c_write_byte_data(ps_data->client,STK_WAIT1_PSGS_REG, wait1);
    if(ret < 0)
        printk("%s: fail, ret=%d\n", __func__, ret);
    return ret;
}

 

static int32_t stk3420_set_psgs_ctrl2(struct stk3420_data *ps_data, uint8_t ctrl2)
{
    int ret;
    ret = stk3420_i2c_write_byte_data(ps_data->client,STK_PS_GS_CTRL2_REG, ctrl2);
    if(ret < 0)
        printk("%s: fail, ret=%d\n", __func__, ret);
    return ret;
}

 

static int32_t stk3420_get_psgs_ctrl2(struct stk3420_data *ps_data)
{
    int ret;
    ret = stk3420_i2c_read_byte_data(ps_data->client,STK_PS_GS_CTRL2_REG);
    if(ret < 0)
        printk("%s: fail, ret=%d\n", __func__, ret);
    return ret;
}

 

static uint32_t stk3420_get_ps_reading(struct stk3420_data *ps_data)
{
    unsigned char value[2];
    int ret;

 

    ret = stk3420_i2c_read_data(ps_data->client, STK_DATA1_PS_REG, 2, &value[0]);
    if(ret < 0) {
        printk("%s: fail, ret=%d\n", __func__, ret);
        return ret;
    }
    return ((value[0]<<8) | value[1]);
}

 

static uint32_t stk3420_get_ges_reading(struct stk3420_data *ps_data)
{
    int ret, len, gsflag;
 int unit_data_size = 0;
 unsigned char ges[8];
 
 gsflag = stk3420_get_gsflag(ps_data);
 if(gsflag < 0)
  return gsflag;
  
 //printk("%s: gsflag=%d\n", __func__, gsflag);
  
 len = gsflag & STK_GSFLG_FIFO_LEN;
 if(len == 0) {
  APS_WARN("%s: gs_fifo_len = 0, gsflag=0x%x\n", __func__, gsflag);
  return 0;
 }
  
 while(len > 0) {
  ret = stk3420_i2c_read_data(ps_data->client, STK_DATA1_GSE_REG, 8, ges);
  if(ret < 0) {
   printk("%s: fail, ret=%d\n", __func__, ret);
   return ret;
  }
  len--;
  unit_data_size++;
  ps_data->ges_last_code[0] = ges[0]<<8 | ges[1];
  ps_data->ges_last_code[1] = ges[2]<<8 | ges[3];
  ps_data->ges_last_code[2] = ges[4]<<8 | ges[5];
  ps_data->ges_last_code[3] = ges[6]<<8 | ges[7];  
  stk3420_report_ges_code(ps_data);
 } 

 

 //printk("stk:%d->%d,%d,%d,%d\n", unit_data_size, ges[0]<<8|ges[1], ges[2]<<8|ges[3], ges[4]<<8|ges[5], ges[6]<<8|ges[7]);
 
 if(gsflag & STK_GSFLG_FIFO_OV) {
  printk("%s: clr gsflag\n", __func__);
  stk3420_set_gsflag(ps_data, 0);  
#ifdef STK_POLL_PS
  printk("%s: Reduce polling time\n", __func__);
  ps_data->ps_poll.poll_delay = ns_to_ktime(STK_FAST_GES_POLL_DELAY_MS * NSEC_PER_MSEC);  
#else
  if(ps_data->reg.fifoctrl_reg >= 8) {
   ps_data->reg.fifoctrl_reg /= 2;
   printk("%s: reduce fifo_thd to 0x%x\n", __func__, ps_data->reg.fifoctrl_reg);
   ret = stk3420_i2c_write_byte_data(ps_data->client, STK_GS_FIFO_CTRL_REG, ps_data->reg.fifoctrl_reg);
   if (ret < 0) {
    printk("%s: write i2c error\n", __func__);
    return ret;
   }  
  }
#endif  
 }
    return unit_data_size;
}

 


static uint32_t stk3420_get_als_reading(struct stk3420_data *ps_data)
{
    int32_t word_data, signal_data;
    unsigned char value[2];
    int ret;
 static int check_singal_data = 0;
 
    ret = stk3420_i2c_read_data(ps_data->client, STK_DATA1_ALS_REG, 2, &value[0]);
    if(ret < 0) {
        printk("%s fail, ret=0x%x", __func__, ret);
        return ret;
    }
    word_data = (value[0]<<8) | value[1];
 
 if(word_data > 60000)
  check_singal_data = 10;
 
 if(check_singal_data > 0)
 {
  check_singal_data--;
  ret = stk3420_i2c_read_data(ps_data->client, 0x5A, 2, value);
  if(ret < 0) {
   printk("%s fail, ret=0x%x", __func__, ret);
   return ret;
  }
  signal_data = (value[0]<<8) | value[1];
  printk("%s: word_data=%5d, signal_data=%5d\n", __func__, word_data, signal_data);
  if(signal_data == 0xFFFF)
  {
   word_data = 0xFFFF;
   check_singal_data = 10;
  }
 }
 
#ifdef STK_ALS_FIR
 word_data = stk3420_als_fir(ps_data, word_data);
#endif

 

    return word_data;
}

 


#ifdef STK_IRS
static int32_t stk3420_get_ir_reading(struct stk3420_data *ps_data)
{
    int32_t word_data, ret;
    unsigned char value[2];
 
    ret = stk3420_i2c_read_data(ps_data->client, STK_DATA1_IRS_REG, 2, value);
    if(ret < 0) {
        printk("%s fail, ret=0x%x", __func__, ret);
        return ret;
    }
    word_data = ((value[0]<<8) | value[1]);
    return word_data;
}
#endif

 

static int32_t stk3420_enable_ges(struct stk3420_data *ps_data, uint8_t enable)
{
    int32_t ret;
    uint8_t w_state_reg;
   
    if(enable == ps_data->ges_enabled)
        return 0;
  
    printk("%s: Enable GES : 0x%x\n", __func__, enable);  
    ret = stk3420_get_state(ps_data);
    if(ret < 0)
        return ret;
    w_state_reg = ret;
  
    if(enable) {
#ifdef STK_QUALCOMM_POWER_CTRL
        ret = stk_device_ctl(ps_data, enable);
        if (ret)
            return ret;
#endif

 

  stk3420_set_wait1_psgs(ps_data, ps_data->reg.wait1_psgs_reg_gs);  
  ret = stk3420_get_psgs_ctrl2(ps_data);
  if(ret < 0)
   return ret; 
  enable &= (STK_PSGS2_EN_NS | STK_PSGS2_EN_EW);
  ret = stk3420_set_psgs_ctrl2(ps_data, enable | ret);
  if(ret < 0)
   return ret; 
   
  if(!ps_data->ps_enabled) {
   w_state_reg |= STK_STATE_EN_WAIT_PSGS_MASK;    
   ret = stk3420_set_state(ps_data, w_state_reg);
   if(ret < 0)
    return ret;
  }
  
#ifdef STK_POLL_PS
  if(!ps_data->ps_enabled) {
   ps_data->ps_poll.poll_delay = ns_to_ktime(STK_DEF_GES_POLL_DELAY_MS * NSEC_PER_MSEC);
   hrtimer_start(&ps_data->ps_poll.hr_timer, ps_data->ps_poll.poll_delay, HRTIMER_MODE_REL);  
  } else {
   ps_data->ps_poll.poll_delay = ns_to_ktime(STK_DEF_GES_POLL_DELAY_MS * NSEC_PER_MSEC);
  }
#else
  ps_data->ps_poll.poll_delay = ns_to_ktime(STK_DEF_GES_POLL_DELAY_MS * NSEC_PER_MSEC);
  hrtimer_start(&ps_data->ps_poll.hr_timer, ps_data->ps_poll.poll_delay, HRTIMER_MODE_REL);  
#endif
        ps_data->ges_enabled = enable;
    } else {
  ret = stk3420_get_psgs_ctrl2(ps_data);
  if(ret < 0)
   return ret; 
  ret = stk3420_set_psgs_ctrl2(ps_data, ret & 0xFC);
  if(ret < 0)
   return ret;  
  
  if(!ps_data->ps_enabled) {
   w_state_reg &= ~(STK_STATE_EN_WAIT_PSGS_MASK | STK_STATE_EN_BGIR_MASK);
   ret = stk3420_set_state(ps_data, w_state_reg);
   if(ret < 0)
    return ret;
  } else {
   stk3420_set_wait1_psgs(ps_data, ps_data->reg.wait1_psgs_reg_ps);
   ps_data->ps_poll.poll_delay = ns_to_ktime(STK_DEF_PS_POLL_DELAY_MS * NSEC_PER_MSEC);  
  }
        ps_data->ges_enabled = 0;
#ifdef STK_POLL_PS
  if(!ps_data->ps_enabled) 
   hrtimer_cancel(&ps_data->ps_poll.hr_timer);  
#else
  if(ps_data->ps_enabled) {
   if(ps_data->tune0.psi_set) {
    hrtimer_cancel(&ps_data->ps_poll.hr_timer);  
   }
  } else {
   hrtimer_cancel(&ps_data->ps_poll.hr_timer);  
  }
#endif
  
#ifdef STK_QUALCOMM_POWER_CTRL
        ret = stk_device_ctl(ps_data, enable);
        if (ret)
            return ret;
#endif
    }

 

    return 0;
}

 

static int32_t stk3420_enable_ps(struct stk3420_data *ps_data, uint8_t enable, uint8_t validate_reg)
{
    int32_t ret;
    uint8_t w_state_reg;
    uint8_t curr_ps_enable;
    uint32_t reading;
    ktime_t first_ps_delay;  

 

    printk("%s: Enable PS : 0x%x\n", __func__, enable);
 
#ifdef STK_QUALCOMM_POWER_CTRL
    if (enable) {
        ret = stk_device_ctl(ps_data, enable);
        if (ret)
            return ret;
    }
#endif
#ifdef STK_CHK_REG
    if(validate_reg) {
        ret = stk3420_validate_n_handle(ps_data->client);
        if(ret < 0)
            printk("stk3420_validate_n_handle fail: %d\n", ret);
    }
#endif /* #ifdef STK_CHK_REG */

 


    curr_ps_enable = ps_data->ps_enabled?1:0;
    if(curr_ps_enable == enable)
        return 0;

 

    if(ps_data->first_boot == true) {
        ps_data->first_boot = false;
    }

 

    ret = stk3420_get_state(ps_data);
    if(ret < 0)
        return ret;
    w_state_reg = ret;

 

    if(enable) {
#ifdef CALI_PS_EVERY_TIME
        ps_data->tune0.psi_set = 0;
        ps_data->tune0.psa = 0;
        ps_data->tune0.psi = 0xFFFF;
 #ifndef QUALCOMM_PLATFORM
        ps_data->ps_thd_h = ps_data->ps_high_thd_boot;
        ps_data->ps_thd_l = ps_data->ps_low_thd_boot;
 #endif
#endif /* #ifdef CALI_PS_EVERY_TIME */
        stk3420_set_ps_thd_h(ps_data, ps_data->ps_thd_h);
        stk3420_set_ps_thd_l(ps_data, ps_data->ps_thd_l);
        printk("%s: HT=%d,LT=%d\n", __func__,
      ps_data->ps_thd_h,
      ps_data->ps_thd_l);
  if(!ps_data->ges_enabled) {
   stk3420_set_wait1_psgs(ps_data, ps_data->reg.wait1_psgs_reg_ps);
  }
  
  w_state_reg |= (STK_STATE_EN_PS_MASK | STK_STATE_EN_WAIT_PSGS_MASK);
  ret = stk3420_set_state(ps_data, w_state_reg);
  if(ret < 0)
   return ret;    

 

#ifdef STK_POLL_PS
        ps_data->ps_distance_last = -1;
   
  if(!ps_data->ges_enabled) {
   ps_data->ps_poll.poll_delay = ns_to_ktime(STK_DEF_PS_POLL_DELAY_MS * NSEC_PER_MSEC);
   first_ps_delay = ns_to_ktime(STK_DEF_PS_POLL_DELAY_MS * NSEC_PER_MSEC * 2);     
   hrtimer_start(&ps_data->ps_poll.hr_timer, first_ps_delay, HRTIMER_MODE_REL);
  }
#else
  if(!ps_data->ges_enabled && ps_data->tune0.psi_set == 0) {
   ps_data->ps_poll.poll_delay = ns_to_ktime(STK_DEF_PS_POLL_DELAY_MS * NSEC_PER_MSEC);
   first_ps_delay = ns_to_ktime(STK_DEF_PS_POLL_DELAY_MS * NSEC_PER_MSEC * 2);     
   hrtimer_start(&ps_data->ps_poll.hr_timer, first_ps_delay, HRTIMER_MODE_REL);
  } 
  
 #ifndef STK_POLL_ALS
        if(!ps_data->als_enabled)
 #endif /* #ifndef STK_POLL_ALS */
  {
   enable_irq(ps_data->irq);
  }
#endif /* #ifdef STK_POLL_PS */
        ps_data->ps_enabled = true;
#ifdef STK_CHK_REG
        if(!validate_reg) {
            ps_data->ps_distance_last = 1;
            reading = stk3420_get_ps_reading(ps_data);
            printk("%s: force report ps input event\n",__func__);
   stk3420_ps_report_distance(ps_data, reading, 1);
        } else
#endif /* #ifdef STK_CHK_REG */
        {
   usleep_range(4000, 5000);
            ret = stk3420_get_flag(ps_data);
            if (ret < 0)
                return ret;
            reading = stk3420_get_ps_reading(ps_data);
   stk3420_ps_report_distance(ps_data, reading, ret & STK_FLG_NF_MASK);   
        }
  
    } else {
#ifdef STK_POLL_PS
  if(!ps_data->ges_enabled) {
   hrtimer_cancel(&ps_data->ps_poll.hr_timer);
  }
#else
  if(!ps_data->tune0.psi_set && !ps_data->ges_enabled) {
   hrtimer_cancel(&ps_data->ps_poll.hr_timer);
  }
 
 #ifndef STK_POLL_ALS
        if(!(ps_data->als_enabled))
 #endif
  {
   disable_irq(ps_data->irq);
  }
#endif
        ps_data->ps_enabled = false;

 

  if(ps_data->ges_enabled) {  
   w_state_reg &= ~(STK_STATE_EN_PS_MASK);
   ret = stk3420_set_state(ps_data, w_state_reg);
   if(ret < 0)
    return ret;  
  }else {
   w_state_reg &= ~(STK_STATE_EN_PS_MASK | STK_STATE_EN_WAIT_PSGS_MASK | STK_STATE_EN_BGIR_MASK);
   ret = stk3420_set_state(ps_data, w_state_reg);
   if(ret < 0)
    return ret;
  
  }
#ifdef STK_QUALCOMM_POWER_CTRL
        ret = stk_device_ctl(ps_data, enable);
        if (ret)
            return ret;
#endif
    }
    return ret;
}

 

static int32_t stk3420_enable_als(struct stk3420_data *ps_data, uint8_t enable)
{
    int32_t ret;
    uint8_t w_state_reg;
    uint8_t curr_als_enable = (ps_data->als_enabled)?1:0;
#ifdef STK_POLL_ALS 
    ktime_t first_als_delay;  
#endif 
#ifdef STK_QUALCOMM_POWER_CTRL
    if (enable) {
        ret = stk_device_ctl(ps_data, enable);
        if (ret)
            return ret;
    }
#endif
 
    if(curr_als_enable == enable)
        return 0;
    printk("%s: Enable ALS : %d\n", __func__, enable);
 
#ifndef STK_POLL_ALS
/*
 #ifdef STK_IRS
    if(enable && !(ps_data->ps_enabled)) {
        ret = stk3420_get_ir_reading(ps_data);
        if(ret > 0)
            ps_data->ir_code = ret;
    }
 #endif
*/
    if (enable) {
        stk3420_set_als_thd_h(ps_data, 0x0000);
        stk3420_set_als_thd_l(ps_data, 0xFFFF);
    }
#endif

 

    ret = stk3420_get_state(ps_data);
    if(ret < 0)
        return ret;
 w_state_reg = (uint8_t)ret;
    if(enable)
        w_state_reg |= STK_STATE_EN_ALS_MASK;
    else
  w_state_reg &= ~(STK_STATE_EN_ALS_MASK); 
    ret = stk3420_set_state(ps_data, w_state_reg);
    if(ret < 0)
        return ret;

 

    if (enable) {
        ps_data->als_enabled = true;
#ifdef STK_POLL_ALS
  first_als_delay = ns_to_ktime(STK_DEF_ALS_POLL_DELAY_MS * NSEC_PER_MSEC * 2);
        hrtimer_start(&ps_data->als_poll.hr_timer, first_als_delay, HRTIMER_MODE_REL);
#else
 #ifndef STK_POLL_PS
        if(!(ps_data->ps_enabled))
 #endif
            enable_irq(ps_data->irq);
#endif

 

    } else {
        ps_data->als_enabled = false;
#ifdef STK_POLL_ALS
        hrtimer_cancel(&ps_data->als_poll.hr_timer);
        // cancel_work_sync(&ps_data->als_poll.work_str);
#else
 #ifndef STK_POLL_PS
        if(!(ps_data->ps_enabled))
 #endif
            disable_irq(ps_data->irq);
#endif

 

#ifdef STK_QUALCOMM_POWER_CTRL
        ret = stk_device_ctl(ps_data, enable);
        if (ret)
            return ret;
#endif
    }
    return ret;
}

 

#ifdef STK_IRS
static int32_t stk3420_enable_irs(struct stk3420_data *ps_data, uint8_t enable)
{
    int32_t ret;
    uint8_t w_state_reg;

 

    printk("%s: Enable IRS : %d\n", __func__, enable); 
    ret = stk3420_get_state(ps_data);
    if(ret < 0)
        return ret;
 w_state_reg = (uint8_t)ret;
    if(enable)
        w_state_reg |= STK_STATE_EN_IRS_MASK;
    else
  w_state_reg &= ~(STK_STATE_EN_IRS_MASK); 
    ret = stk3420_set_state(ps_data, w_state_reg);
    if(ret < 0)
        return ret;
 return 0;
}

 


#endif

 

#ifdef STK_ALS_FIR
static uint16_t stk3420_als_fir(struct stk3420_data *ps_data, uint16_t als)
{
    int index;
    int firlen = atomic_read(&ps_data->firlength);

 

    if(ps_data->fir.number < firlen) {
        ps_data->fir.raw[ps_data->fir.number] = als;
        ps_data->fir.sum += als;
        ps_data->fir.number++;
        ps_data->fir.idx++;
    } else {
        index = ps_data->fir.idx % firlen;
        ps_data->fir.sum -= ps_data->fir.raw[index];
        ps_data->fir.raw[index] = als;
        ps_data->fir.sum += als;
        ps_data->fir.idx++;
        return ps_data->fir.sum/firlen;
    }
 return als;
}
#endif

 


static ssize_t stk_als_code_show(struct device *dev, struct device_attribute *attr, char *buf)
{
    struct stk3420_data *ps_data =  dev_get_drvdata(dev);
    int32_t reading;

 

    reading = stk3420_get_als_reading(ps_data);
    return scnprintf(buf, PAGE_SIZE, "%d\n", reading);
}

 

static ssize_t stk_als_enable_show(struct device *dev, struct device_attribute *attr, char *buf)
{
    struct stk3420_data *ps_data =  dev_get_drvdata(dev);
    int32_t ret;

 

    ret = stk3420_get_state(ps_data);
    if(ret < 0)
        return ret;
    ret = (ret & STK_STATE_EN_ALS_MASK)?1:0;

 

    return scnprintf(buf, PAGE_SIZE, "%d\n", ret);
}

 

static ssize_t stk_als_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
{
    struct stk3420_data *ps_data = dev_get_drvdata(dev);
    uint8_t en;
    if (sysfs_streq(buf, "1")) {
        en = 1;
    } else if (sysfs_streq(buf, "0")) {
            en = 0;
 } else {
  printk("%s, invalid value %d\n", __func__, *buf);
  return -EINVAL;
 }

 

    mutex_lock(&ps_data->io_lock);
    stk3420_enable_als(ps_data, en);
    mutex_unlock(&ps_data->io_lock);
    return size;
}

 

static ssize_t stk_als_lux_show(struct device *dev, struct device_attribute *attr, char *buf)
{
    struct stk3420_data *ps_data = dev_get_drvdata(dev);
    int32_t als_reading;
    uint32_t als_lux;
    als_reading = stk3420_get_als_reading(ps_data);
    als_lux = stk3420_alscode2lux(ps_data, als_reading);
    return scnprintf(buf, PAGE_SIZE, "%d lux\n", als_lux);
}

 

static ssize_t stk_als_lux_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
{
    struct stk3420_data *ps_data =  dev_get_drvdata(dev);
    unsigned long value = 0;
    int ret;
    ret = kstrtoul(buf, 16, &value);
    if(ret < 0) {
        printk("%s:kstrtoul failed, ret=0x%x\n", __func__, ret);
        return ret;
    }
 stk3420_als_report_lux(ps_data, value);
    return size;
}

 


static ssize_t stk_als_transmittance_show(struct device *dev, struct device_attribute *attr, char *buf)
{
    struct stk3420_data *ps_data =  dev_get_drvdata(dev);
    int32_t transmittance;
    transmittance = ps_data->als_transmittance;
    return scnprintf(buf, PAGE_SIZE, "%d\n", transmittance);
}

 


static ssize_t stk_als_transmittance_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
{
    struct stk3420_data *ps_data =  dev_get_drvdata(dev);
    unsigned long value = 0;
    int ret;
    ret = kstrtoul(buf, 10, &value);
    if(ret < 0) {
        printk("%s:kstrtoul failed, ret=0x%x\n", __func__, ret);
        return ret;
    }
    ps_data->als_transmittance = value;
    return size;
}

 

#ifdef STK_POLL_ALS
static ssize_t stk_als_delay_show(struct device *dev, struct device_attribute *attr, char *buf)
{
    struct stk3420_data *ps_data =  dev_get_drvdata(dev);
    int64_t delay;
    mutex_lock(&ps_data->io_lock);
    delay = ktime_to_ns(ps_data->als_poll.poll_delay);
    mutex_unlock(&ps_data->io_lock);
    return scnprintf(buf, PAGE_SIZE, "%lld\n", delay);
}

 

static ssize_t stk_als_delay_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
{
    uint64_t value = 0;
    int ret;
    struct stk3420_data *ps_data =  dev_get_drvdata(dev);
    ret = kstrtoull(buf, 10, &value);
    if(ret < 0) {
        printk("%s:kstrtoull failed, ret=0x%x\n", __func__, ret);
        return ret;
    }
    printk("%s: set als poll delay=%lld\n", __func__, value);
    if(value < STK_MIN_ALS_POLL_DELAY_NS) {
        printk("%s: delay is too small\n", __func__);
        value = STK_MIN_ALS_POLL_DELAY_NS;
    }
    mutex_lock(&ps_data->io_lock);
    if(value != ktime_to_ns(ps_data->als_poll.poll_delay))
        ps_data->als_poll.poll_delay = ns_to_ktime(value);
#ifdef STK_ALS_FIR
    ps_data->fir.number = 0;
    ps_data->fir.idx = 0;
    ps_data->fir.sum = 0;
#endif
    mutex_unlock(&ps_data->io_lock);
    return size;
}
#endif

 

#ifdef STK_IRS
static ssize_t stk_irs_enable_show(struct device *dev, struct device_attribute *attr, char *buf)
{
    struct stk3420_data *ps_data =  dev_get_drvdata(dev);
    int32_t ret;

 

    ret = stk3420_get_state(ps_data);
    if(ret < 0)
        return ret;
    ret = (ret & STK_STATE_EN_IRS_MASK)?1:0;

 

    return scnprintf(buf, PAGE_SIZE, "%d\n", ret);
}

 

static ssize_t stk_irs_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
{
    struct stk3420_data *ps_data = dev_get_drvdata(dev);
    uint8_t en;
    if (sysfs_streq(buf, "1")) {
        en = 1;
    } else if (sysfs_streq(buf, "0")) {
            en = 0;
 }else {
  printk("%s, invalid value %d\n", __func__, *buf);
  return -EINVAL;
 }

 

    mutex_lock(&ps_data->io_lock);
    stk3420_enable_irs(ps_data, en);
    mutex_unlock(&ps_data->io_lock);
    return size;
}

 

static ssize_t stk_als_ir_code_show(struct device *dev, struct device_attribute *attr, char *buf)
{
    struct stk3420_data *ps_data =  dev_get_drvdata(dev);
    int32_t reading;
    reading = stk3420_get_ir_reading(ps_data);
    return scnprintf(buf, PAGE_SIZE, "%d\n", reading);
}
#endif

 

#ifdef STK_ALS_FIR
static ssize_t stk_als_firlen_show(struct device *dev, struct device_attribute *attr, char *buf)
{
    struct stk3420_data *ps_data =  dev_get_drvdata(dev);
    int len = atomic_read(&ps_data->firlength);

 

    printk("%s: len = %2d, idx = %2d\n", __func__, len, ps_data->fir.idx);
    printk("%s: sum = %5d, ave = %5d\n", __func__, ps_data->fir.sum, ps_data->fir.sum/len);

 

    return scnprintf(buf, PAGE_SIZE, "%d\n", len);
}

 


static ssize_t stk_als_firlen_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
{
    uint64_t value = 0;
    int ret;
    struct stk3420_data *ps_data =  dev_get_drvdata(dev);
    ret = kstrtoull(buf, 10, &value);
    if(ret < 0) {
        printk("%s:kstrtoull failed, ret=0x%x\n", __func__, ret);
        return ret;
    }

 

    if(value > MAX_FIR_LEN) {
        printk("%s: firlen exceed maximum filter length\n", __func__);
    } else
        if (value < 1) {
            atomic_set(&ps_data->firlength, 1);
            memset(&ps_data->fir, 0x00, sizeof(ps_data->fir));
        } else {
            atomic_set(&ps_data->firlength, value);
            memset(&ps_data->fir, 0x00, sizeof(ps_data->fir));
        }
    return size;
}
#endif  /* #ifdef STK_ALS_FIR */

 

static ssize_t stk_ges_code_show(struct device *dev, struct device_attribute *attr, char *buf)
{
    struct stk3420_data *ps_data =  dev_get_drvdata(dev);
    int ret;

 

    if(!ps_data->ges_enabled) {
        printk("%s: ges is disabled\n", __func__); 
        return 0;
 }
    ret = stk3420_get_ges_reading(ps_data);
    if(ret < 0)
        return ret;
 
    return scnprintf(buf, PAGE_SIZE, "%5d,%5d,%5d,%5d\n", ps_data->ges_last_code[0], ps_data->ges_last_code[1], ps_data->ges_last_code[2], ps_data->ges_last_code[3]);
}

 


static int32_t stk_ges_input_touch_event(struct stk3420_data *ps_data, struct device *dev, int value)
{
 int x1, y1, x2, y2;
 int delta_x, delta_y, i;
    uint8_t ges = 0;
 
 x1 = y1 = x2 = y2 = 0;

 

 switch (value) {
 case 1:
  printk("%s: ges input event ^^^^\n",__func__); 
  x1 = x2 = 200;
  y1 = 500;
  y2 = 100;
  break;
 case 2:
  printk("%s: ges input event vvvv\n",__func__); 
  x1 = x2 = 200;
  y1 = 100;
  y2 = 500;
  break;
 case 8:
  printk("%s: ges input event <<<<\n",__func__);
  x1 = 500;
  x2 = 100;
  y1 = y2 = 200;
  break;
 case 16:
  printk("%s: ges input event >>>>\n",__func__); 
  x1 = 100;
  x2 = 500;
  y1 = y2 = 200;
  break;
 case 32:
  ges = KEY_VOLUMEDOWN;
  printk("%s: ges input event near\n",__func__);
  break;
 case 48:
  ges = KEY_VOLUMEUP;
  printk("%s: ges input event far\n",__func__);
  break;
 default:
  ges = value;
  printk("%s, unknown key %d, force report it\n", __func__, (int)value);  
 }

 

 if(ges) { 
  input_report_key(ps_data->ges_input_dev, ges, 1);
  input_report_key(ps_data->ges_input_dev, ges, 0);
  input_sync(ps_data->ges_input_dev);
  return 0;
 }
 
 delta_x = (x2 - x1) / 5;
 delta_y = (y2 - y1) / 5;
 for (i = 0; i < 5; i++) {
  input_report_key(ps_data->ges_input_dev, BTN_TOUCH, 1);
  input_report_abs(ps_data->ges_input_dev, ABS_X, x1 + delta_x * i);
  input_report_abs(ps_data->ges_input_dev, ABS_Y, y1 + delta_y * i); 
  input_report_key(ps_data->ges_input_dev, BTN_TOUCH, 0);
 
 /*
  input_report_abs(ps_data->ges_input_dev, ABS_MT_TRACKING_ID, 0);
  input_report_abs(ps_data->ges_input_dev, ABS_MT_TOUCH_MAJOR, 200);
  input_report_abs(ps_data->ges_input_dev, ABS_MT_POSITION_Y, (y1 + delta_y * i));
  input_report_abs(ps_data->ges_input_dev, ABS_MT_POSITION_X, (x1 + delta_x * i));
  input_report_abs(ps_data->ges_input_dev, ABS_MT_WIDTH_MAJOR, 1);
  input_mt_sync(ps_data->ges_input_dev);
  input_sync(ps_data->ges_input_dev);
  */
  msleep(20);
 }
 //input_mt_sync(ps_data->ges_input_dev);
 input_sync(ps_data->ges_input_dev);
 return 0;
}

 

static int32_t stk_ges_input_key_event(struct stk3420_data *ps_data, struct device *dev, int value)
{
    uint8_t ges;
 
 switch(value) {
 case 3:
  //printk("%s: ges input event, not detected\n",__func__);
 case 0:
  return 0;
 case 1:
  ges = KEY_UP;
  printk("%s: ges input event ^^^^\n",__func__);
  break;
 case 2:
  ges = KEY_DOWN;
  printk("%s: ges input event vvvv\n",__func__);
  break;
 case 8:
  ges = KEY_LEFT;
  printk("%s: ges input event <<<<\n",__func__);
  break;
 case 16:
  ges = KEY_RIGHT;
  printk("%s: ges input event >>>>\n",__func__);
  break;  
 case 32:
  ges = KEY_VOLUMEDOWN;
  printk("%s: ges input event near\n",__func__);
  break;
 case 48:
  ges = KEY_VOLUMEUP;
  printk("%s: ges input event far\n",__func__);
  break;
 default:
  ges = value;
  printk("%s, unknown key %d, force report it\n", __func__, (int)value);
  //return -EINVAL;
 }
 
 input_report_key(ps_data->ges_input_dev, ges, 1);
 input_report_key(ps_data->ges_input_dev, ges, 0);
 input_sync(ps_data->ges_input_dev);
 return 0;
}

 

static ssize_t stk_ges_code_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
{
    struct stk3420_data *ps_data =  dev_get_drvdata(dev);
    unsigned long value = 0;
    int ret;

 

    ret = kstrtoul(buf, 16, &value);
    if(ret < 0) {
        printk("%s:kstrtoul failed, ret=%d\n", __func__, ret);
        return ret;
    }
 
 if(ps_data->ges_enabled & STK_EN_GES_TOUCN) {
  stk_ges_input_touch_event(ps_data, dev, value);
 } else {
  stk_ges_input_key_event(ps_data, dev, value);
 }
 
    return size;
}

 

static ssize_t stk_ges_last_code_show(struct device *dev, struct device_attribute *attr, char *buf)
{
    struct stk3420_data *ps_data =  dev_get_drvdata(dev);

 

    if(!ps_data->ges_enabled) {
        printk("%s: ges is disabled\n", __func__); 
        return 0;
 }
    return scnprintf(buf, PAGE_SIZE, "%5d,%5d,%5d,%5d\n", ps_data->ges_last_code[0],
              ps_data->ges_last_code[1],
              ps_data->ges_last_code[2],
              ps_data->ges_last_code[3]);

 

static ssize_t stk_ges_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
{
    struct stk3420_data *ps_data =  dev_get_drvdata(dev);
    unsigned long value = 0;
    int ret;

 

    ret = kstrtoul(buf, 10, &value);
    if(ret < 0) {
        printk("%s:kstrtoul failed, ret=%d\n", __func__, ret);
        return ret;
    }

 

 mutex_lock(&ps_data->io_lock);
 stk3420_enable_ges(ps_data, value);
 mutex_unlock(&ps_data->io_lock);

 

    return size;
}

 

static ssize_t stk_ges_enable_show(struct device *dev, struct device_attribute *attr, char *buf)
{
    struct stk3420_data *ps_data =  dev_get_drvdata(dev);
    return scnprintf(buf, PAGE_SIZE, "%d\n", ps_data->ges_enabled);
}

 


static ssize_t stk_ps_code_show(struct device *dev, struct device_attribute *attr, char *buf)
{
    struct stk3420_data *ps_data =  dev_get_drvdata(dev);
    uint32_t reading;
    reading = stk3420_get_ps_reading(ps_data);
    return scnprintf(buf, PAGE_SIZE, "%d\n", reading);
}

 

static ssize_t stk_ps_enable_show(struct device *dev, struct device_attribute *attr, char *buf)
{
    int32_t ret;
    struct stk3420_data *ps_data =  dev_get_drvdata(dev);

 

    ret = stk3420_get_state(ps_data);
    if(ret < 0)
        return ret;
    ret = (ret & STK_STATE_EN_PS_MASK)?1:0;

 

    return scnprintf(buf, PAGE_SIZE, "%d\n", ret);
}

 

static ssize_t stk_ps_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
{
    struct stk3420_data *ps_data =  dev_get_drvdata(dev);
    uint8_t en;
    if (sysfs_streq(buf, "1"))
        en = 1;
    else
        if (sysfs_streq(buf, "0"))
            en = 0;
        else {
            printk("%s, invalid value %d\n", __func__, *buf);
            return -EINVAL;
        }

 

    mutex_lock(&ps_data->io_lock);
    stk3420_enable_ps(ps_data, en, 1);
    mutex_unlock(&ps_data->io_lock);
    return size;
}

 


static ssize_t stk_ps_distance_show(struct device *dev, struct device_attribute *attr, char *buf)
{
    struct stk3420_data *ps_data =  dev_get_drvdata(dev);
    int32_t ret;
    uint32_t reading, dist;
 
    ret = stk3420_get_flag(ps_data);
    if(ret < 0)
        return ret;
    reading = stk3420_get_ps_reading(ps_data);
 dist = stk3420_ps_report_distance(ps_data, reading, ret & STK_FLG_NF_MASK); 
    return scnprintf(buf, PAGE_SIZE, "%d\n", dist);
}

 


static ssize_t stk_ps_distance_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
{
    struct stk3420_data *ps_data =  dev_get_drvdata(dev);
    unsigned long value = 0;
    int ret;
 uint32_t reading;
  
    ret = kstrtoul(buf, 10, &value);
    if(ret < 0) {
        printk("%s:kstrtoul failed, ret=0x%x\n", __func__, ret);
        return ret;
    }
    reading = stk3420_get_ps_reading(ps_data); 
 stk3420_ps_report_distance(ps_data, reading, value);    
    return size;
}

 


static ssize_t stk_ps_code_thd_l_show(struct device *dev, struct device_attribute *attr, char *buf)
{
 unsigned char value[2];
    struct stk3420_data *ps_data =  dev_get_drvdata(dev); 
 int ret;
 
 ret = stk3420_i2c_read_data(ps_data->client, STK_THDL1_PS_REG, 2, value);
 if(ret < 0) { 
        printk("%s: Fail to read STK_THDH1_PS_REG, ret=0x%x\n", __func__, ret);
  return ret;
 } 
    return scnprintf(buf, PAGE_SIZE, "%d\n", value[0]<<8 | value[1]);
}

 


static ssize_t stk_ps_code_thd_l_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
{
    struct stk3420_data *ps_data =  dev_get_drvdata(dev);
    unsigned long value = 0;
    int ret;
    ret = kstrtoul(buf, 10, &value);
    if(ret < 0) {
        printk("%s:kstrtoul failed, ret=0x%x\n", __func__, ret);
        return ret;
    }
    stk3420_set_ps_thd_l(ps_data, value);
    return size;
}

 

static ssize_t stk_ps_code_thd_h_show(struct device *dev, struct device_attribute *attr, char *buf)
{
 unsigned char value[2];
    struct stk3420_data *ps_data =  dev_get_drvdata(dev); 
 int ret;
 
 ret = stk3420_i2c_read_data(ps_data->client, STK_THDH1_PS_REG, 2, value);
 if(ret < 0) { 
        printk("%s: Fail to read STK_THDH1_PS_REG, ret=0x%x\n", __func__, ret);
  return ret;
 }
    return scnprintf(buf, PAGE_SIZE, "%d\n", value[0]<<8 | value[1]);
}

 


static ssize_t stk_ps_code_thd_h_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
{
    struct stk3420_data *ps_data =  dev_get_drvdata(dev);
    unsigned long value = 0;
    int ret;
    ret = kstrtoul(buf, 10, &value);
    if(ret < 0) {
        printk("%s:kstrtoul failed, ret=0x%x\n", __func__, ret);
        return ret;
    }
    stk3420_set_ps_thd_h(ps_data, value);
    return size;
}

 


static ssize_t stk_all_reg_show(struct device *dev, struct device_attribute *attr, char *buf)
{
    int32_t ps_reg[0x2A];
    uint8_t cnt;
    int len = 0;
    struct stk3420_data *ps_data =  dev_get_drvdata(dev);

 

    for(cnt=0; cnt<0x28; cnt++) {
        ps_reg[cnt] = stk3420_i2c_read_byte_data(ps_data->client, (cnt));
        if(ps_reg[cnt] < 0) {
            printk("%s fail, ret=%d", __func__, ps_reg[cnt]);
            return -EINVAL;
        } else {
            printk("reg[0x%2X]=0x%2X\n", cnt, ps_reg[cnt]);
            len += scnprintf(buf+len, PAGE_SIZE-len, "[%2X]%2X,", cnt, ps_reg[cnt]);
        }
    }
    ps_reg[cnt] = stk3420_i2c_read_byte_data(ps_data->client, STK_PDT_ID_REG);
    if(ps_reg[cnt] < 0) {
        printk("%s fail, ret=%d", __func__, ps_reg[cnt]);
        return -EINVAL;
    }
    cnt++;
    ps_reg[cnt] = stk3420_i2c_read_byte_data(ps_data->client, STK_RSRVD_REG);
    if(ps_reg[cnt] < 0) {
        printk("%s fail, ret=%d", __func__, ps_reg[cnt]);
        return -EINVAL;
    }
    printk("reg[0x%x]=0x%2X\n", STK_PDT_ID_REG, ps_reg[cnt]);
    printk("reg[0x%x]=0x%2X\n", STK_RSRVD_REG, ps_reg[cnt]);
    len += scnprintf(buf+len, PAGE_SIZE-len, "[%2X]%2X,[%2X]%2X\n", STK_PDT_ID_REG, ps_reg[cnt-1], STK_RSRVD_REG, ps_reg[cnt]);
    return len;
}

 

static ssize_t stk_status_show(struct device *dev, struct device_attribute *attr, char *buf)
{
    int32_t ps_reg[0x28];
    uint8_t cnt;
    struct stk3420_data *ps_data =  dev_get_drvdata(dev);
    for(cnt=0; cnt<0x28; cnt++) {
        ps_reg[cnt] = stk3420_i2c_read_byte_data(ps_data->client, (cnt));
        if(ps_reg[cnt] < 0) {
            printk("%s fail, ret=%d", __func__, ps_reg[cnt]);
            return -EINVAL;
        } else {
            printk("reg[0x%2X]=0x%2X\n", cnt, ps_reg[cnt]);
        }
    }

 

    return scnprintf(buf, PAGE_SIZE, "[PS=%2X] [ALS=%2X] [GS=%2X] [WAIT1_PSGS=%3x ms] [NEAR/FAR=%2X] [FLAG_PSINT=%2X] [FLAG_ALSINT=%2X] [FLAG_GSINT=%2X]\n",
                     ps_reg[0]&0x01,(ps_reg[0]&0x02)>>1,(ps_reg[0x1D]&0x03),((ps_reg[0]&0x04)>>2)*ps_reg[5]*78/100,
                     ps_reg[16]&0x01,(ps_reg[16]&0x10)>>4, (ps_reg[16]&0x20)>>5, (ps_reg[16]&0x08)>>3);
}

 

static ssize_t stk_recv_show(struct device *dev, struct device_attribute *attr, char *buf)
{
    struct stk3420_data *ps_data =  dev_get_drvdata(dev);
    return scnprintf(buf, PAGE_SIZE, "0x%04X\n", atomic_read(&ps_data->recv_reg));
}

 


static ssize_t stk_recv_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
{
    unsigned long value = 0;
    int ret;
    int32_t recv_data;
    struct stk3420_data *ps_data =  dev_get_drvdata(dev);

 

    if((ret = kstrtoul(buf, 16, &value)) < 0) {
        printk("%s:kstrtoul failed, ret=0x%x\n", __func__, ret);
        return ret;
    }
    recv_data = stk3420_i2c_read_byte_data(ps_data->client,value);
    printk("%s: reg 0x%x=0x%x\n", __func__, (int)value, recv_data);
    atomic_set(&ps_data->recv_reg, recv_data);
    return size;
}

 


static ssize_t stk_send_show(struct device *dev, struct device_attribute *attr, char *buf)
{
    return 0;
}

 


static ssize_t stk_send_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
{
    int addr, cmd;
    int32_t ret, i;
    char *token[10];
    struct stk3420_data *ps_data =  dev_get_drvdata(dev);

 

    for (i = 0; i < 2; i++)
        token[i] = strsep((char **)&buf, " ");
    if((ret = kstrtoul(token[0], 16, (unsigned long *)&(addr))) < 0) {
        printk("%s:kstrtoul failed, ret=0x%x\n", __func__, ret);
        return ret;
    }
    if((ret = kstrtoul(token[1], 16, (unsigned long *)&(cmd))) < 0) {
        printk("%s:kstrtoul failed, ret=0x%x\n", __func__, ret);
        return ret;
    }
    printk("%s: write reg 0x%x=0x%x\n", __func__, addr, cmd);

 

    ret = stk3420_i2c_write_byte_data(ps_data->client, (unsigned char)addr, (unsigned char)cmd);
    if (0 != ret) {
        printk("%s: stk3420_i2c_write_byte_data fail\n", __func__);
        return ret;
    }

 

    return size;
}

 

static ssize_t stk_ps_cali_show(struct device *dev, struct device_attribute *attr, char *buf)
{
    struct stk3420_data *ps_data =  dev_get_drvdata(dev);
    int32_t word_data;
    unsigned char value[2];
    int ret;

 

    ret = stk3420_i2c_read_data(ps_data->client, 0x20, 2, &value[0]);
    if(ret < 0) {
        printk("%s fail, ret=0x%x", __func__, ret);
        return ret;
    }
    word_data = (value[0]<<8) | value[1];

 

    ret = stk3420_i2c_read_data(ps_data->client, 0x22, 2, &value[0]);
    if(ret < 0) {
        printk("%s fail, ret=0x%x", __func__, ret);
        return ret;
    }
    word_data += ((value[0]<<8) | value[1]);

 

    printk("%s: psi_set=%d, psa=%d,psi=%d, word_data=%d\n", __func__,
             ps_data->tune0.psi_set, ps_data->tune0.psa, ps_data->tune0.psi, word_data);
#ifdef CALI_PS_EVERY_TIME
    printk("%s: boot HT=%d, LT=%d\n", __func__, ps_data->ps_high_thd_boot, ps_data->ps_low_thd_boot);
#endif
    return 0;
}

 

static ssize_t stk_ps_maxdiff_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
{
    struct stk3420_data *ps_data =  dev_get_drvdata(dev);
    unsigned long value = 0;
    int ret;

 

    if((ret = kstrtoul(buf, 10, &value)) < 0) {
        printk("%s:kstrtoul failed, ret=0x%x\n", __func__, ret);
        return ret;
    }
    ps_data->tune0.stk_max_min_diff = (int) value;
    return size;
}

 


static ssize_t stk_ps_maxdiff_show(struct device *dev, struct device_attribute *attr, char *buf)
{
    struct stk3420_data *ps_data =  dev_get_drvdata(dev);
    return scnprintf(buf, PAGE_SIZE, "%d\n", ps_data->tune0.stk_max_min_diff);
}

 

static ssize_t stk_ps_ltnct_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
{
    struct stk3420_data *ps_data =  dev_get_drvdata(dev);
    unsigned long value = 0;
    int ret;

 

    if((ret = kstrtoul(buf, 10, &value)) < 0) {
        printk("%s:kstrtoul failed, ret=0x%x\n", __func__, ret);
        return ret;
    }
    ps_data->tune0.stk_lt_n_ct = (int) value;
    return size;
}

 

static ssize_t stk_ps_ltnct_show(struct device *dev, struct device_attribute *attr, char *buf)
{
    struct stk3420_data *ps_data =  dev_get_drvdata(dev);
    return scnprintf(buf, PAGE_SIZE, "%d\n", ps_data->tune0.stk_lt_n_ct);
}

 

static ssize_t stk_ps_htnct_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
{
    struct stk3420_data *ps_data =  dev_get_drvdata(dev);
    unsigned long value = 0;
    int ret;

 

    if((ret = kstrtoul(buf, 10, &value)) < 0) {
        printk("%s:kstrtoul failed, ret=0x%x\n", __func__, ret);
        return ret;
    }
    ps_data->tune0.stk_ht_n_ct = (int) value;
    return size;
}

 

static ssize_t stk_ps_htnct_show(struct device *dev, struct device_attribute *attr, char *buf)
{
    struct stk3420_data *ps_data =  dev_get_drvdata(dev);
    return scnprintf(buf, PAGE_SIZE, "%d\n", ps_data->tune0.stk_ht_n_ct);
}

 

static struct device_attribute als_enable_attribute = __ATTR(enable,0664,stk_als_enable_show,stk_als_enable_store);
static struct device_attribute als_lux_attribute = __ATTR(lux,0664,stk_als_lux_show,stk_als_lux_store);
static struct device_attribute als_code_attribute = __ATTR(code, 0444, stk_als_code_show, NULL);
static struct device_attribute als_transmittance_attribute = __ATTR(transmittance,0664,stk_als_transmittance_show,stk_als_transmittance_store);
#ifdef STK_POLL_ALS
static struct device_attribute als_poll_delay_attribute = __ATTR(delay,0664,stk_als_delay_show,stk_als_delay_store);
#endif
#ifdef STK_IRS
static struct device_attribute als_ir_code_attribute = __ATTR(ircode,0444,stk_als_ir_code_show,NULL);
static struct device_attribute als_enable_irs_attribute = __ATTR(enable_irs,0666,stk_irs_enable_show,stk_irs_enable_store);
#endif
#ifdef STK_ALS_FIR
static struct device_attribute als_firlen_attribute = __ATTR(firlen,0664,stk_als_firlen_show,stk_als_firlen_store);
#endif

 

static struct attribute *stk_als_attrs [] = {
    &als_enable_attribute.attr,
    &als_lux_attribute.attr,
    &als_code_attribute.attr,
    &als_transmittance_attribute.attr,
#ifdef STK_POLL_ALS 
    &als_poll_delay_attribute.attr,
#endif 
#ifdef STK_IRS
    &als_ir_code_attribute.attr,
    &als_enable_irs_attribute.attr,
#endif 
#ifdef STK_ALS_FIR
    &als_firlen_attribute.attr,
#endif
    NULL
};

 

static struct attribute_group stk_als_attribute_group = {
#ifndef QUALCOMM_PLATFORM
    .name = "driver",
#endif
    .attrs = stk_als_attrs,
};

 

static struct device_attribute ges_enable_attribute = __ATTR(enable,0666,stk_ges_enable_show,stk_ges_enable_store);
static struct device_attribute ges_code_attribute = __ATTR(code, 0664, stk_ges_code_show, stk_ges_code_store);
static struct device_attribute ges_last_code_attribute = __ATTR(lastcode, 0444, stk_ges_last_code_show, NULL);
static struct device_attribute ges_recv_attribute = __ATTR(recv,0664,stk_recv_show,stk_recv_store);
static struct device_attribute ges_send_attribute = __ATTR(send,0664,stk_send_show, stk_send_store);

 

static struct attribute *stk_ges_attrs [] = {
    &ges_enable_attribute.attr,
    &ges_code_attribute.attr,
    &ges_last_code_attribute.attr,
    &ges_recv_attribute.attr,
    &ges_send_attribute.attr,
    NULL
};

 

static struct attribute_group stk_dae_attribute_group = {
    .name = "driver",
    .attrs = stk_ges_attrs,
};

 

static struct device_attribute ps_enable_attribute = __ATTR(enable,0664,stk_ps_enable_show,stk_ps_enable_store);
static struct device_attribute ps_distance_attribute = __ATTR(distance,0664,stk_ps_distance_show, stk_ps_distance_store);
static struct device_attribute ps_code_attribute = __ATTR(code, 0444, stk_ps_code_show, NULL);
static struct device_attribute ps_code_thd_l_attribute = __ATTR(codethdl,0664,stk_ps_code_thd_l_show,stk_ps_code_thd_l_store);
static struct device_attribute ps_code_thd_h_attribute = __ATTR(codethdh,0664,stk_ps_code_thd_h_show,stk_ps_code_thd_h_store);
static struct device_attribute ps_recv_attribute = __ATTR(recv,0664,stk_recv_show,stk_recv_store);
static struct device_attribute ps_send_attribute = __ATTR(send,0664,stk_send_show, stk_send_store);
static struct device_attribute all_reg_attribute = __ATTR(allreg, 0444, stk_all_reg_show, NULL);
static struct device_attribute status_attribute = __ATTR(status, 0444, stk_status_show, NULL);
static struct device_attribute ps_cali_attribute = __ATTR(cali,0444,stk_ps_cali_show, NULL);
static struct device_attribute ps_maxdiff_attribute = __ATTR(maxdiff,0664,stk_ps_maxdiff_show, stk_ps_maxdiff_store);
static struct device_attribute ps_ltnct_attribute = __ATTR(ltnct,0664,stk_ps_ltnct_show, stk_ps_ltnct_store);
static struct device_attribute ps_htnct_attribute = __ATTR(htnct,0664,stk_ps_htnct_show, stk_ps_htnct_store);

 

static struct attribute *stk_ps_attrs [] = {
    &ps_enable_attribute.attr,
    &ps_distance_attribute.attr,
    &ps_code_attribute.attr,
    &ps_code_thd_l_attribute.attr,
    &ps_code_thd_h_attribute.attr,
    &ps_recv_attribute.attr,
    &ps_send_attribute.attr,
    &all_reg_attribute.attr,
    &status_attribute.attr,
    &ps_cali_attribute.attr,
    &ps_maxdiff_attribute.attr,
    &ps_ltnct_attribute.attr,
    &ps_htnct_attribute.attr,
    NULL
};

 

static struct attribute_group stk_ps_attribute_group = {
#ifndef QUALCOMM_PLATFORM
    .name = "driver",
#endif
    .attrs = stk_ps_attrs,
};

 

static int stk_ps_val(struct stk3420_data *ps_data)
{
    int mode;
    int32_t word_data, lii;
    unsigned char value[6];
    int ret;

 

    ret = stk3420_i2c_read_data(ps_data->client, 0x48, 6, value);
    if(ret < 0) {
        printk("%s fail, ret=0x%x", __func__, ret);
        return ret;
    }
    word_data = (value[0]<<8) | value[1];
    word_data += ((value[4]<<8) | value[5]);

 

    mode = (ps_data->reg.psgsctrl1_reg) & 0x0F;
    if(mode == 0x0) {
        lii = 400;
    } else if (mode == 0x1) {
  lii = 800;
 } else if (mode == 0x2) {
  lii = 1600;
 }else if (mode == 0x3) {
  lii = 3200;
 }else if (mode == 0x4) {
  lii = 6400;  
 } else {
  printk("%s: unsupported PS_IT(0x%x)\n", __func__, mode);
  return -1;
 }

 

    if(word_data > lii) {
        printk("%s: word_data=%d, lii=%d\n", __func__, word_data, lii);
        return 0xFFFF;
    }
    return 0;
}

 


static int stk_ps_tune0_boot_final(struct stk3420_data *ps_data)
{
    int ret;

 

 printk("%s\n", __func__);
 
    ps_data->tune0.tune_zero_init_proc = false;
    ret = stk3420_i2c_write_byte_data(ps_data->client, STK_INT_REG, ps_data->reg.int_reg);
    if (ret < 0) {
        printk("%s: write i2c error\n", __func__);
        return ret;
    }

 

 if(!ps_data->ps_enabled) {
  ret = stk3420_set_state(ps_data, 0);
  if(ret < 0)
   return ret; 
#ifdef STK_POLL_PS
  if(!ps_data->ges_enabled)
#endif
  {
   hrtimer_cancel(&ps_data->ps_poll.hr_timer);   
  }
 }
    if(ps_data->tune0.data_count == -1) {
        printk("%s: exceed limit\n", __func__);
        return 0;
    }

 

    ps_data->tune0.psa = ps_data->tune0.ps_stat_data[0];
    ps_data->tune0.psi = ps_data->tune0.ps_stat_data[2];

 

#ifdef CALI_PS_EVERY_TIME
    ps_data->ps_high_thd_boot = ps_data->tune0.ps_stat_data[1] + ps_data->tune0.stk_ht_n_ct*3;
    ps_data->ps_low_thd_boot = ps_data->tune0.ps_stat_data[1] + ps_data->tune0.stk_lt_n_ct*3;
    ps_data->ps_thd_h = ps_data->ps_high_thd_boot ;
    ps_data->ps_thd_l = ps_data->ps_low_thd_boot ;
#else
    ps_data->ps_thd_h = ps_data->tune0.ps_stat_data[1] + ps_data->tune0.stk_ht_n_ct;
    ps_data->ps_thd_l = ps_data->tune0.ps_stat_data[1] + ps_data->tune0.stk_lt_n_ct;
#endif
    stk3420_set_ps_thd_h(ps_data, ps_data->ps_thd_h);
    stk3420_set_ps_thd_l(ps_data, ps_data->ps_thd_l);
    printk("%s: set HT=%d,LT=%d\n", __func__, ps_data->ps_thd_h,  ps_data->ps_thd_l);
    return 0;
}

 

static int32_t stk_ps_tune0_boot_get_data(struct stk3420_data *ps_data)
{
    uint32_t ps_adc;
    int ret;

 

    ret = stk_ps_val(ps_data);
    if(ret == 0xFFFF) {
        ps_data->tune0.data_count = -1;
        stk_ps_tune0_boot_final(ps_data);
        return 0;
    }

 

    ps_adc = stk3420_get_ps_reading(ps_data);
    printk("%s: ps_adc #%d=%d\n", __func__, ps_data->tune0.data_count, ps_adc);
    if(ps_adc < 0)
        return ps_adc;

 

    ps_data->tune0.ps_stat_data[1] += ps_adc;
    if(ps_adc > ps_data->tune0.ps_stat_data[0])
        ps_data->tune0.ps_stat_data[0] = ps_adc;
    if(ps_adc < ps_data->tune0.ps_stat_data[2])
        ps_data->tune0.ps_stat_data[2] = ps_adc;
    ps_data->tune0.data_count++;

 

    if(ps_data->tune0.data_count == 5) {
        ps_data->tune0.ps_stat_data[1]  /= ps_data->tune0.data_count;
        stk_ps_tune0_boot_final(ps_data);
    }

 

    return 0;
}

 

static int stk_ps_tune0_boot_init(struct stk3420_data *ps_data)
{
    int32_t ret = 0;
    uint8_t w_state_reg;

 

    ps_data->tune0.psi_set = 0;
    ps_data->tune0.ps_stat_data[0] = 0;
    ps_data->tune0.ps_stat_data[2] = 9999;
    ps_data->tune0.ps_stat_data[1] = 0;
    ps_data->tune0.data_count = 0;

 

    ps_data->tune0.tune_zero_init_proc = true;
    ret = stk3420_i2c_write_byte_data(ps_data->client, STK_INT_REG, 0);
    if (ret < 0) {
        printk("%s: write i2c error\n", __func__);
        return ret;
    }

 

    w_state_reg = (STK_STATE_EN_PS_MASK | STK_STATE_EN_WAIT_PSGS_MASK);
    ret = stk3420_set_state(ps_data, w_state_reg);
    if(ret < 0)
        return ret; 
    ret = hrtimer_start(&ps_data->ps_poll.hr_timer, ps_data->ps_poll.poll_delay, HRTIMER_MODE_REL);
 //printk("%s: start timer, ret=%d\n", __func__, ret);
    return 0;
}

 

static int stk_ps_tune0_func(struct stk3420_data *ps_data, uint32_t ps_reading)
{
    int ret, diff;
    //unsigned char value[2];

 

    if(!(ps_data->ps_enabled))
        return 0;

 

    ret = stk_ps_val(ps_data);
 if(ret != 0) 
  return ret;

 

 if(ps_reading > ps_data->tune0.psa) {
  ps_data->tune0.psa = ps_reading;
  printk("%s: update psa: psa=%d,psi=%d\n", __func__, ps_data->tune0.psa, ps_data->tune0.psi);
 }
 if(ps_reading < ps_data->tune0.psi) {
  ps_data->tune0.psi = ps_reading;
  printk("%s: update psi: psa=%d,psi=%d\n", __func__, ps_data->tune0.psa, ps_data->tune0.psi);
 }

 

    diff = ps_data->tune0.psa - ps_data->tune0.psi;
    if(diff > ps_data->tune0.stk_max_min_diff) {
        ps_data->tune0.psi_set = ps_data->tune0.psi;
        ps_data->ps_thd_h = ps_data->tune0.psi + ps_data->tune0.stk_ht_n_ct;
        ps_data->ps_thd_l = ps_data->tune0.psi + ps_data->tune0.stk_lt_n_ct;

 

#ifdef CALI_PS_EVERY_TIME
        if(ps_data->ps_thd_h > ps_data->ps_high_thd_boot) {
            ps_data->ps_high_thd_boot = ps_data->ps_thd_h;
            ps_data->ps_low_thd_boot = ps_data->ps_thd_l;
            printk("%s: update boot HT=%d, LT=%d\n", __func__, ps_data->ps_high_thd_boot, ps_data->ps_low_thd_boot);
        }
#endif

 

        stk3420_set_ps_thd_h(ps_data, ps_data->ps_thd_h);
        stk3420_set_ps_thd_l(ps_data, ps_data->ps_thd_l);
        printk("%s: FAE tune0 psa-psi(%d) > STK_DIFF found\n", __func__, diff);
  printk("%s: HT=%d, LT=%d\n", __func__, ps_data->ps_thd_h, ps_data->ps_thd_l);

 

#ifndef STK_POLL_PS
  if(!ps_data->ges_enabled)
  {
   hrtimer_cancel(&ps_data->ps_poll.hr_timer);  
  }
#endif  
    }

 

    return 0;
}

 

#ifdef STK_IRS
static int32_t stk_als_irs_ready(struct stk3420_data *ps_data)
{
 int32_t reading;
 if(ps_data->ps_distance_last != 0) {
  reading = stk3420_get_ir_reading(ps_data);
  if(reading > 0)
   ps_data->ir_code = reading;
 }
 return reading;
}
#endif

 

static uint32_t stk_als_ready(struct stk3420_data *ps_data)
{
    uint32_t reading, reading_lux, als_comperator;
 
    reading = stk3420_get_als_reading(ps_data);
    if(reading < 0)
        return reading;

 

    if(ps_data->ir_code) {
        ps_data->als_correct_factor = 1000;
        if(reading < STK_IRC_MAX_ALS_CODE && reading > STK_IRC_MIN_ALS_CODE &&
                ps_data->ir_code > STK_IRC_MIN_IR_CODE) {
            als_comperator = reading * STK_IRC_ALS_NUMERA / STK_IRC_ALS_DENOMI;
            if(ps_data->ir_code > als_comperator)
                ps_data->als_correct_factor = STK_IRC_ALS_CORREC;
        }
        printk("%s: als=%d, ir=%d, als_correct_factor=%d", __func__,
                 reading, ps_data->ir_code, ps_data->als_correct_factor);
        ps_data->ir_code = 0;
    }
    reading = reading * ps_data->als_correct_factor / 1000;

 

    reading_lux = stk3420_alscode2lux(ps_data, reading);
#ifdef STK_POLL_ALS 
 if (abs(ps_data->als_lux_last - reading_lux) >= STK_ALS_CHANGE_THD)
  stk3420_als_report_lux(ps_data, reading_lux);
#else  
 stk3420_als_report_lux(ps_data, reading_lux);
#endif 
 return reading;
}

 


static void stk_ps_ges_ready(struct stk3420_data *ps_data)
{
 stk3420_get_ges_reading(ps_data);
 return;
}

 

static void stk_ps_poll_pscode(struct stk3420_data *ps_data)
{
    uint32_t reading;
    uint8_t org_flag_reg;

 

 reading = stk3420_get_ps_reading(ps_data);
 if(!ps_data->tune0.psi_set)
  stk_ps_tune0_func(ps_data, reading);

 

#ifdef STK_POLL_PS
 org_flag_reg = stk3420_get_flag(ps_data);
 if(org_flag_reg < 0)
  return;  
  
 stk3420_ps_report_distance(ps_data, reading, org_flag_reg & STK_FLG_NF_MASK);    
#endif
 return;
}

 


#ifdef STK_POLL_ALS
static enum hrtimer_restart stk_als_timer_func(struct hrtimer *timer)
{
    struct stk3420_poll *poll_str = container_of(timer, struct stk3420_poll, hr_timer);
    struct stk3420_data *ps_data = container_of(poll_str, struct stk3420_data, als_poll); 
    queue_work(ps_data->als_poll.wq, &ps_data->als_poll.work_str);
    hrtimer_forward_now(&ps_data->als_poll.hr_timer, ps_data->als_poll.poll_delay);
    return HRTIMER_RESTART;
}

 

 

 

static void stk_als_poll_work_func(struct work_struct *work)
{
    struct stk3420_poll *poll_str = container_of(work, struct stk3420_poll, work_str);
    struct stk3420_data *ps_data = container_of(poll_str, struct stk3420_data, als_poll);
    int32_t flag_reg;

 

 //printk("%s\n", __func__);
    flag_reg = stk3420_get_flag(ps_data);
    if(flag_reg < 0)
        return;
  
#ifdef STK_IRS
    if(flag_reg & STK_FLG_IRSDR_MASK)
  stk_als_irs_ready(ps_data);
#endif  
  
 stk_als_ready(ps_data);

 

    return;
}
#endif /* #ifdef STK_POLL_ALS */

 

static enum hrtimer_restart stk_ps_timer_func(struct hrtimer *timer)
{
    struct stk3420_poll *poll_str = container_of(timer, struct stk3420_poll, hr_timer);
    struct stk3420_data *ps_data = container_of(poll_str, struct stk3420_data, ps_poll);
    queue_work(ps_data->ps_poll.wq, &ps_data->ps_poll.work_str);
    hrtimer_forward_now(&ps_data->ps_poll.hr_timer, ps_data->ps_poll.poll_delay);
    return HRTIMER_RESTART;
}

 

static void stk_ps_poll_work_func(struct work_struct *work)
{
    struct stk3420_poll *poll_str = container_of(work, struct stk3420_poll, work_str);
    struct stk3420_data *ps_data = container_of(poll_str, struct stk3420_data, ps_poll);

 

 if(ps_data->tune0.tune_zero_init_proc) {
  stk_ps_tune0_boot_get_data(ps_data);
 }
 else if(ps_data->ps_enabled) {
   stk_ps_poll_pscode(ps_data);
 }
 
 if(ps_data->ges_enabled) {
  stk_ps_ges_ready(ps_data);
 }
 
    return;
}

 


#if (!defined(STK_POLL_PS) || !defined(STK_POLL_ALS))
static void stk_work_func(struct work_struct *work)
{
    uint32_t reading = 0;
#if (STK_PS_INT_MODE != 0x01)
    int32_t ret;
    uint8_t disable_flag = 0;
    int32_t org_flag_reg;
#endif 
#ifndef CONFIG_STK_PS_ALS_USE_CHANGE_THRESHOLD
    uint32_t nLuxIndex;
#endif
    struct stk3420_data *ps_data = container_of(work, struct stk3420_data, stk_work);

 

#if (STK_PS_INT_MODE == 0x01)
    int32_t near_far_state;
 
    near_far_state = gpio_get_value(ps_data->int_number); 
    reading = stk3420_get_ps_reading(ps_data);
 stk3420_ps_report_distance(ps_data, reading, near_far_state);   
#else
    org_flag_reg = stk3420_get_flag(ps_data);
    if(org_flag_reg < 0)
        goto err_i2c_rw;
 
#ifdef STK_IRS
    if(org_flag_reg & STK_FLG_IRSDR_MASK)
  stk_als_irs_ready(ps_data);
#endif  

 

    if(org_flag_reg & STK_FLG_IRFAIL_MASK)
  printk("%s: BGIR failed\n", __func__);
  
    if (org_flag_reg & STK_FLG_ALSINT_MASK) {
        disable_flag |= STK_FLG_ALSINT_MASK;
  reading = stk_als_ready(ps_data);
 #ifdef CONFIG_STK_PS_ALS_USE_CHANGE_THRESHOLD
        stk3420_als_set_new_thd(ps_data, reading);
 #else
        nLuxIndex = stk3420_get_lux_interval_index(reading);
        stk3420_set_als_thd_h(ps_data, code_threshold_table[nLuxIndex]);
        stk3420_set_als_thd_l(ps_data, code_threshold_table[nLuxIndex-1]);
 #endif //CONFIG_STK_PS_ALS_USE_CHANGE_THRESHOLD  
    }
 
    if (org_flag_reg & STK_FLG_PSINT_MASK) {
        disable_flag |= STK_FLG_PSINT_MASK;  
    }
 
 if(ps_data->ps_enabled) {
        // reading = stk3420_get_ps_reading(ps_data);
  stk3420_ps_report_distance(ps_data, reading, org_flag_reg & STK_FLG_NF_MASK);     
 }
 
 ret = stk3420_set_flag(ps_data, org_flag_reg, disable_flag);
 if(ret < 0)
  goto err_i2c_rw;
  
#endif
    usleep_range(1000, 2000);
    enable_irq(ps_data->irq);
    return;

 

err_i2c_rw:
    msleep(30);
    enable_irq(ps_data->irq);
    return;
}

 

static irqreturn_t stk_oss_irq_handler(int irq, void *data)
{
    struct stk3420_data *pData = data;
    disable_irq_nosync(irq);
    queue_work(pData->stk_wq,&pData->stk_work);
    return IRQ_HANDLED;
}
#endif /* #if (!defined(STK_POLL_PS) || !defined(STK_POLL_ALS)) */

 

 

 

static void stk3420_report_ges_code(struct stk3420_data *ps_data)
{
 input_report_rel(ps_data->dae_input_dev, REL_X, ps_data->ges_last_code[0]);
 input_report_rel(ps_data->dae_input_dev, REL_Y, ps_data->ges_last_code[1]);
 input_report_rel(ps_data->dae_input_dev, REL_Z, ps_data->ges_last_code[2]);
 input_report_rel(ps_data->dae_input_dev, REL_MISC, ps_data->ges_last_code[3]);
 input_sync(ps_data->dae_input_dev);
 return;
}

 

static uint32_t stk3420_ps_report_distance(struct stk3420_data *ps_data, uint32_t ps_code, uint32_t nf_status)
{
 int32_t distance = 0;
 
 distance =  nf_status ? 5 : 0;
 if(ps_data->ps_distance_last != distance) {
  ps_data->ps_distance_last = distance;
  input_report_abs(ps_data->ps_input_dev, ABS_DISTANCE, distance);
  input_sync(ps_data->ps_input_dev);
  wake_lock_timeout(&ps_data->ps_wakelock, 3*HZ);
  printk("%s: ps input event %d cm, ps code = %d\n",__func__, distance, ps_code);
 }

 

 return distance;
}

 

static void stk3420_als_report_lux(struct stk3420_data *ps_data, uint32_t lux)
{
 ps_data->als_lux_last = lux;
 input_report_abs(ps_data->als_input_dev, ABS_MISC, lux);
 input_sync(ps_data->als_input_dev);
 printk("%s: als input event %d lux\n",__func__, lux);
}

 

static uint32_t stk3420_alscode2lux(struct stk3420_data *ps_data, uint32_t alscode)
{
    alscode += ((alscode<<7)+(alscode<<3)+(alscode>>1));
    alscode<<=3;
    alscode/=ps_data->als_transmittance;
    return alscode;
}

 

static uint32_t stk3420_lux2alscode(struct stk3420_data *ps_data, uint32_t lux)
{
    lux*=ps_data->als_transmittance;
    lux/=1100;
    if (unlikely(lux>=(1<<16)))
        lux = (1<<16) -1;
    return lux;
}

 

#ifndef CONFIG_STK_PS_ALS_USE_CHANGE_THRESHOLD
static void stk3420_als_init_code_thd_table(struct stk3420_data *ps_data)
{
    uint32_t i,j;
    uint32_t alscode;

 

    code_threshold_table[0] = 0;
    printk( "alscode[0]=%d\n",0);
    for (i=1,j=0; i<LUX_THD_TABLE_SIZE; i++,j++) {
        alscode = stk3420_lux2alscode(ps_data, lux_threshold_table[j]);
        printk("alscode[%d]=%d\n",i,alscode);
        code_threshold_table[i] = (uint16_t)(alscode);
    }
    code_threshold_table[i] = 0xffff;
    printk("alscode[%d]=%d\n",i,alscode);
}

 

static uint32_t stk3420_get_lux_interval_index(uint16_t alscode)
{
    uint32_t i;
    for (i=1; i<=LUX_THD_TABLE_SIZE; i++) {
        if ((alscode>=code_threshold_table[i-1])&&(alscode<code_threshold_table[i])) {
            return i;
        }
    }
    return LUX_THD_TABLE_SIZE;
}
#else
static void stk3420_als_set_new_thd(struct stk3420_data *ps_data, uint32_t alscode)
{
    int32_t high_thd,low_thd;
    high_thd = alscode + stk3420_lux2alscode(ps_data, STK_ALS_CHANGE_THD);
    low_thd = alscode - stk3420_lux2alscode(ps_data, STK_ALS_CHANGE_THD);
    if (high_thd >= (1<<16))
        high_thd = (1<<16) -1;
    if (low_thd <0)
        low_thd = 0;
    stk3420_set_als_thd_h(ps_data, (uint16_t)high_thd);
    stk3420_set_als_thd_l(ps_data, (uint16_t)low_thd);
}
#endif // CONFIG_STK_PS_ALS_USE_CHANGE_THRESHOLD

 


#ifdef STK_CHK_REG
static int stk3420_chk_reg_valid(struct stk3420_data *ps_data)
{
    unsigned char value[9];
    int ret;
 
    ret = stk3420_i2c_read_data(ps_data->client, STK_PS_GS_CTRL1_REG, 9, &value[0]);
    if(ret < 0) {
        printk("%s: fail, ret=%d\n", __func__, ret);
        return ret;
    }

 

    if(value[0] != ps_data->reg.psgsctrl1_reg) {
        printk("%s: invalid reg 0x01=0x%2x\n", __func__, value[0]);
        return 0xFF;
    }
    if(value[1] != ps_data->reg.alsctrl1_reg) {
        printk("%s: invalid reg 0x02=0x%2x\n", __func__, value[1]);
        return 0xFF;
    }
    if(value[2] != ps_data->reg.ledctrl_reg) {
        printk("%s: invalid reg 0x03=0x%2x\n", __func__, value[2]);
        return 0xFF;
    }
    if(value[3] != ps_data->reg.int_reg) {
        printk("%s: invalid reg 0x04=0x%2x\n", __func__, value[3]);
        return 0xFF;
    }
 /*
    if(value[4] != ps_data->reg.wait1_psgs_reg) {
        printk("%s: invalid reg 0x05=0x%2x\n", __func__, value[4]);
        return 0xFF;
    }
 */
    if(value[5] != ((ps_data->ps_thd_h & 0xFF00) >> 8)) {
        printk("%s: invalid reg 0x06=0x%2x\n", __func__, value[5]);
        return 0xFF;
    }
    if(value[6] != (ps_data->ps_thd_h & 0x00FF)) {
        printk("%s: invalid reg 0x07=0x%2x\n", __func__, value[6]);
        return 0xFF;
    }
    if(value[7] != ((ps_data->ps_thd_l & 0xFF00) >> 8)) {
        printk("%s: invalid reg 0x08=0x%2x\n", __func__, value[7]);
        return 0xFF;
    }
    if(value[8] != (ps_data->ps_thd_l & 0x00FF)) {
        printk("%s: invalid reg 0x09=0x%2x\n", __func__, value[8]);
        return 0xFF;
    }

 

    ret = stk3420_i2c_read_data(ps_data->client, STK_PS_GS_CTRL2_REG, 1, &value[0]);
    if(ret < 0) {
        printk("%s: fail, ret=%d\n", __func__, ret);
        return ret;
    } 
 
    return 0;
}

 

static int stk3420_validate_n_handle(struct i2c_client *client)
{
    struct stk3420_data *ps_data = i2c_get_clientdata(client);
    int ret;

 

    ret = stk3420_chk_reg_valid(ps_data);
    if(ret < 0) {
        printk("stk3420_chk_reg_valid fail: %d\n", ret);
        return ret;
    }

 

    if(ret == 0xFF) {
        printk("%s: Re-init chip\n", __func__);

 

        ret = stk3420_init_all_reg(ps_data);
        if(ret < 0)
            return ret;

 

#ifdef STK_ALS_FIR
        memset(&ps_data->fir, 0x00, sizeof(ps_data->fir));
#endif
        return 0xFF;
    }
    return 0;
}
#endif /* #ifdef STK_CHK_REG */

 

static int32_t stk3420_init_all_setting(struct i2c_client *client, struct stk3420_platform_data *plat_data)
{
    int32_t ret;
    struct stk3420_data *ps_data = i2c_get_clientdata(client);
  
    ret = stk3420_init_all_reg(ps_data);
    if(ret < 0)
        return ret;

 

    ps_data->als_enabled = false;
    ps_data->ps_enabled = false;
    ps_data->re_enable_als = false;
    ps_data->re_enable_ps = false;
    ps_data->ir_code = 0;
    ps_data->als_correct_factor = 1000;
    ps_data->first_boot = true;
#ifndef CONFIG_STK_PS_ALS_USE_CHANGE_THRESHOLD
    stk3420_als_init_code_thd_table(ps_data);
#endif

 


#ifdef STK_ALS_FIR
    memset(&ps_data->fir, 0x00, sizeof(ps_data->fir));
    atomic_set(&ps_data->firlength, STK_FIR_LEN);
#endif
    atomic_set(&ps_data->recv_reg, 0);
    ps_data->re_enable_ges = 0;
    ps_data->ps_distance_last = 1;
    return 0;
}

 

#if (!defined(STK_POLL_PS) || !defined(STK_POLL_ALS))
static int stk_setup_irq(struct i2c_client *client)
{
    int irq, ret = -EIO;
    struct stk3420_data *ps_data = i2c_get_clientdata(client);

 

 if (!gpio_is_valid(ps_data->int_number)) {
  printk("%s: invalid gpio pin %d\n", __func__, ps_data->int_number);
  return -1;
 }
 
#ifdef SPREADTRUM_PLATFORM
    irq = sprd_alloc_gpio_irq(ps_data->int_number);
 printk("%s:stk3420 irq num==%d\n",__func__,irq);
#else
    irq = gpio_to_irq(ps_data->int_number);
#endif
    printk("%s: int pin #=%d, irq=%d\n",__func__, ps_data->int_number, irq);
 
    if (irq <= 0) {
        printk("irq number is not specified, irq # = %d, int pin=%d\n",irq, ps_data->int_number);
        return irq;
    }
    ps_data->irq = irq;
    ret = gpio_request(ps_data->int_number,"stk-int");
    if(ret < 0) {
        printk("%s: gpio_request failed, ret=%d", __func__, ret);
        return ret;
    }
    ret = gpio_direction_input(ps_data->int_number);
    if(ret < 0) {
        printk("%s: gpio_direction_input failed, ret=%d", __func__, ret);
        return ret;
    }
#if (STK_PS_INT_MODE == 0x01)
    ret = request_any_context_irq(irq, stk_oss_irq_handler, IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING, DEVICE_NAME, ps_data);
#else
    ret = request_any_context_irq(irq, stk_oss_irq_handler, IRQF_TRIGGER_LOW, DEVICE_NAME, ps_data);
#endif
    if (ret < 0) {
        APS_WARN("%s: request_any_context_irq(%d) failed for (%d)\n", __func__, irq, ret);
        goto err_request_any_context_irq;
    }
    disable_irq(irq);

 

    return 0;
err_request_any_context_irq:
#ifdef SPREADTRUM_PLATFORM
    sprd_free_gpio_irq(ps_data->int_number);
#else
 if (gpio_is_valid(ps_data->int_number))
  gpio_free(ps_data->int_number);
#endif
    return ret;
}
#endif

 


static int stk3420_suspend(struct device *dev)
{
    struct stk3420_data *ps_data = dev_get_drvdata(dev);
#if (defined(STK_CHK_REG) || !defined(STK_POLL_PS))
    int ret;
#endif

 

#ifndef STK_POLL_PS
    struct i2c_client *client = to_i2c_client(dev);
#endif

 

    printk("%s", __func__);
#ifndef SPREADTRUM_PLATFORM
    mutex_lock(&ps_data->io_lock);
#endif
#ifdef STK_CHK_REG
    ret = stk3420_validate_n_handle(ps_data->client);
    if(ret < 0) {
        printk("stk3420_validate_n_handle fail: %d\n", ret);
    } else
        if (ret == 0xFF) {
            if(ps_data->ps_enabled)
                stk3420_enable_ps(ps_data, 1, 0);
        }
#endif /* #ifdef STK_CHK_REG */
    if(ps_data->ges_enabled) {
        ps_data->re_enable_ges = ps_data->ges_enabled;
        stk3420_enable_ges(ps_data, 0);
    }
#ifndef SPREADTRUM_PLATFORM
    if(ps_data->als_enabled) {
        printk("%s: Enable ALS : 0\n", __func__);
        stk3420_enable_als(ps_data, 0);
        ps_data->re_enable_als = true;
    }
#endif
    if(ps_data->ps_enabled) {
#ifdef STK_POLL_PS
        wake_lock(&ps_data->ps_nosuspend_wl);
#else
        if(device_may_wakeup(&client->dev)) {
            ret = enable_irq_wake(ps_data->irq);
            if (ret)
                APS_WARN("%s: set_irq_wake(%d) failed, ret=(%d)\n", __func__, ps_data->irq, ret);
        } else {
            printk("%s: not support wakeup source", __func__);
        }
#endif
    }
#ifndef SPREADTRUM_PLATFORM
    mutex_unlock(&ps_data->io_lock);
#endif
    return 0;
}

 

static int stk3420_resume(struct device *dev)
{
    struct stk3420_data *ps_data = dev_get_drvdata(dev);
#if (defined(STK_CHK_REG) || !defined(STK_POLL_PS))
    int ret;
#endif

 

#ifndef STK_POLL_PS
    struct i2c_client *client = to_i2c_client(dev);
#endif

 

    printk("%s", __func__);
#ifndef SPREADTRUM_PLATFORM
    mutex_lock(&ps_data->io_lock);
#endif
#ifdef STK_CHK_REG
    ret = stk3420_validate_n_handle(ps_data->client);
    if(ret < 0) {
        printk("stk3420_validate_n_handle fail: %d\n", ret);
    } else
        if (ret == 0xFF) {
            if(ps_data->ps_enabled)
                stk3420_enable_ps(ps_data, 1, 0);
        }
#endif /* #ifdef STK_CHK_REG */
    if(ps_data->re_enable_ges) {
        stk3420_enable_ges(ps_data, ps_data->re_enable_ges);
        ps_data->re_enable_ges = 0;
    }
#ifndef SPREADTRUM_PLATFORM
    if(ps_data->re_enable_als) {
        printk("%s: Enable ALS : 1\n", __func__);
        stk3420_enable_als(ps_data, 1);
        ps_data->re_enable_als = false;
    }
#endif
    if(ps_data->ps_enabled) {
#ifdef STK_POLL_PS
        wake_unlock(&ps_data->ps_nosuspend_wl);
#else
        if(device_may_wakeup(&client->dev)) {
            ret = disable_irq_wake(ps_data->irq);
            if (ret)
                APS_WARN("%s: disable_irq_wake(%d) failed, ret=(%d)\n", __func__, ps_data->irq, ret);
        }
#endif
    }
#ifndef SPREADTRUM_PLATFORM
    mutex_unlock(&ps_data->io_lock);
#endif
    return 0;
}

 

static const struct dev_pm_ops stk3420_pm_ops = {
    SET_SYSTEM_SLEEP_PM_OPS(stk3420_suspend, stk3420_resume)
};

 

//#ifdef CONFIG_HAS_EARLYSUSPEND
#if 1
static void stk3420_early_suspend(struct early_suspend *h)
{

 

}

 

static void stk3420_late_resume(struct early_suspend *h)
{

 

}
#endif //#ifdef CONFIG_HAS_EARLYSUSPEND

 

 

 


#ifdef CONFIG_OF
static int stk_parse_dt(struct device *dev,
                        struct stk3420_platform_data *pdata)
{
    int rc;
    struct device_node *np = dev->of_node;
    u32 temp_val;

 

    pdata->int_number = of_get_named_gpio_flags(np, "stk,irq-gpio",
                     0, &pdata->int_flags);
    if (pdata->int_number < 0) {
        printk("Unable to read irq-gpio\n");
        return pdata->int_number;
    }

 

    rc = of_property_read_u32(np, "stk,transmittance", &temp_val);
    if (!rc)
        pdata->transmittance = temp_val;
    else {
        printk("Unable to read transmittance\n");
        return rc;
    }
    printk("transmittance=%d\n", temp_val); 

 

    rc = of_property_read_u32(np, "stk,psgsctrl-reg", &temp_val);
    if (!rc)
        pdata->psgsctrl1_reg = (u8)temp_val;
    else {
        printk("Unable to read psgsctrl-reg\n");
        return rc;
    }

 

    rc = of_property_read_u32(np, "stk,alsctrl1-reg", &temp_val);
    if (!rc)
        pdata->alsctrl1_reg = (u8)temp_val;
    else {
        printk("Unable to read alsctrl1-reg\n");
        return rc;
    }

 

    rc = of_property_read_u32(np, "stk,ledctrl-reg", &temp_val);
    if (!rc)
        pdata->ledctrl_reg = (u8)temp_val;
    else {
        printk("Unable to read ledctrl-reg\n");
        return rc;
    }

 

    rc = of_property_read_u32(np, "stk,wait1_psgs-reg_ps", &temp_val);
    if (!rc)
        pdata->wait1_psgs_reg_ps = (u8)temp_val;
    else {
        printk("Unable to read wait1_psgs-reg_ps\n");
        return rc;
    }

 

    rc = of_property_read_u32(np, "stk,wait1_psgs-reg_gs", &temp_val);
    if (!rc)
        pdata->wait1_psgs_reg_gs = (u8)temp_val;
    else {
        printk("Unable to read wait1_psgs-reg_gs\n");
        return rc;
    }
 
    rc = of_property_read_u32(np, "stk,alsctrl2-reg", &temp_val);
    if (!rc)
        pdata->alsctrl2_reg = (u8)temp_val;
    else {
        printk("Unable to read alsctrl2-reg\n");
        return rc;
    }

 

    rc = of_property_read_u32(np, "stk,wait_als-reg", &temp_val);
    if (!rc)
        pdata->wait_als_reg = (u8)temp_val;
    else {
        printk("Unable to read wait_als-reg\n");
        return rc;
    }

 

    rc = of_property_read_u32(np, "stk,wait2_ps-reg", &temp_val);
    if (!rc)
        pdata->wait2_ps_reg = (u8)temp_val;
    else {
        printk("Unable to read wait2_ps-reg\n");
        return rc;
    }

 

    rc = of_property_read_u32(np, "stk,psgsctrl2-reg", &temp_val);
    if (!rc)
        pdata->psgsctrl2_reg = (u8)temp_val;
    else {
        printk("Unable to read psgsctrl2-reg\n");
        return rc;
    }
 
 rc = of_property_read_u32(np, "stk,fifoctrl-reg", &temp_val); 
    if (!rc)
        pdata->fifoctrl_reg = (u16)temp_val;
    else {
        printk("Unable to read fifoctrl_reg\n");
        return rc;
    } 
    rc = of_property_read_u32(np, "stk,ps-thd-h", &temp_val);
    if (!rc)
        pdata->ps_thd_h = (u16)temp_val;
    else {
        printk("Unable to read ps-thd-h\n");
        return rc;
    }

 

    rc = of_property_read_u32(np, "stk,ps-thd-l", &temp_val);
    if (!rc)
        pdata->ps_thd_l = (u16)temp_val;
    else {
        printk("Unable to read ps-thd-l\n");
        return rc;
    }

 

    return 0;
}
#else
static int stk_parse_dt(struct device *dev,
                        struct stk3420_platform_data *pdata)
{
    return -ENODEV;
}
#endif /* !CONFIG_OF */

 

static int stk_set_wq(struct stk3420_data *ps_data)
{
#ifdef STK_POLL_ALS
    ps_data->als_poll.wq = create_singlethread_workqueue("stk_als_wq");
    INIT_WORK(&ps_data->als_poll.work_str, stk_als_poll_work_func);
    hrtimer_init(&ps_data->als_poll.hr_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
    ps_data->als_poll.poll_delay = ns_to_ktime(STK_DEF_ALS_POLL_DELAY_MS * NSEC_PER_MSEC);
    ps_data->als_poll.hr_timer.function = stk_als_timer_func;
#endif
//#ifdef STK_POLL_PS
    ps_data->ps_poll.wq = create_singlethread_workqueue("stk_ps_wq");
    INIT_WORK(&ps_data->ps_poll.work_str, stk_ps_poll_work_func);
    hrtimer_init(&ps_data->ps_poll.hr_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
    ps_data->ps_poll.poll_delay = ns_to_ktime(STK_DEF_PS_POLL_DELAY_MS * NSEC_PER_MSEC);
    ps_data->ps_poll.hr_timer.function = stk_ps_timer_func;
//#endif
#if (!defined(STK_POLL_ALS) || !defined(STK_POLL_PS))
    ps_data->stk_wq = create_singlethread_workqueue("stk_wq");
    INIT_WORK(&ps_data->stk_work, stk_work_func);
#endif
    return 0;
}

 


static void stk_del_wq(struct stk3420_data *ps_data)
{
#ifdef STK_POLL_ALS
    hrtimer_try_to_cancel(&ps_data->als_poll.hr_timer);
    destroy_workqueue(ps_data->als_poll.wq);
#endif
#ifdef STK_POLL_PS
    hrtimer_try_to_cancel(&ps_data->ps_poll.hr_timer);
    destroy_workqueue(ps_data->ps_poll.wq);
#endif
#if (!defined(STK_POLL_ALS) || !defined(STK_POLL_PS))
    destroy_workqueue(ps_data->stk_wq);
#endif
    return;
}

 

static int stk_set_input_devices(struct stk3420_data *ps_data)
{
    int ret;

 

    ps_data->als_input_dev = input_allocate_device();
    if (ps_data->als_input_dev==NULL) {
        printk("%s: could not allocate als device\n", __func__);
        ret = -ENOMEM;
        return ret;
    }
    ps_data->ps_input_dev = input_allocate_device();
    if (ps_data->ps_input_dev==NULL) {
        printk("%s: could not allocate ps device\n", __func__);
        ret = -ENOMEM;
        return ret;
    }
    ps_data->als_input_dev->name = ALS_NAME;
    ps_data->ps_input_dev->name = PS_NAME;
    set_bit(EV_ABS, ps_data->als_input_dev->evbit);
    set_bit(EV_ABS, ps_data->ps_input_dev->evbit);
    input_set_abs_params(ps_data->als_input_dev, ABS_MISC, 0, stk3420_alscode2lux(ps_data, (1<<16)-1), 0, 0);
    input_set_abs_params(ps_data->ps_input_dev, ABS_DISTANCE, 0,1, 0, 0);
    ret = input_register_device(ps_data->als_input_dev);
    if (ret<0) {
        printk("%s: can not register als input device\n", __func__);
        return ret;
    }
    ret = input_register_device(ps_data->ps_input_dev);
    if (ret<0) {
        printk("%s: can not register ps input device\n", __func__);
        return ret;
    }

 

    ret = sysfs_create_group(&ps_data->als_input_dev->dev.kobj, &stk_als_attribute_group);
    if (ret < 0) {
        printk("%s:could not create sysfs group for als\n", __func__);
        return ret;
    }
    ret = sysfs_create_group(&ps_data->ps_input_dev->dev.kobj, &stk_ps_attribute_group);
    if (ret < 0) {
        printk("%s:could not create sysfs group for ps\n", __func__);
        return ret;
    }
    input_set_drvdata(ps_data->als_input_dev, ps_data);
    input_set_drvdata(ps_data->ps_input_dev, ps_data);

 

    ps_data->ges_input_dev = input_allocate_device();
    if (ps_data->ges_input_dev==NULL) {
        printk("%s: could not allocate ges device\n", __func__);
        ret = -ENOMEM;
        return ret;
    }
    ps_data->ges_input_dev->name = GES_NAME;
    ps_data->ges_input_dev->evbit[0] = BIT_MASK(EV_KEY);
 
    set_bit(KEY_PAGEUP, ps_data->ges_input_dev->keybit);
    set_bit(KEY_PAGEDOWN, ps_data->ges_input_dev->keybit);
    set_bit(KEY_VOLUMEUP, ps_data->ges_input_dev->keybit);
    set_bit(KEY_VOLUMEDOWN, ps_data->ges_input_dev->keybit);
   
    set_bit(KEY_LEFT, ps_data->ges_input_dev->keybit);
    set_bit(KEY_RIGHT, ps_data->ges_input_dev->keybit);
    set_bit(KEY_UP, ps_data->ges_input_dev->keybit);
    set_bit(KEY_DOWN, ps_data->ges_input_dev->keybit);
   
    set_bit(195, ps_data->ges_input_dev->keybit);
    set_bit(196, ps_data->ges_input_dev->keybit);
    set_bit(197, ps_data->ges_input_dev->keybit);
    set_bit(198, ps_data->ges_input_dev->keybit); 

 

#if 1 
    ps_data->ges_input_dev->evbit[0] = BIT_MASK(ABS_DISTANCE);
 input_set_abs_params(ps_data->ges_input_dev, ABS_DISTANCE, 0, 1, 0, 0);
 set_bit(ABS_MT_TOUCH_MAJOR, ps_data->ges_input_dev->absbit);
 set_bit(ABS_MT_POSITION_X, ps_data->ges_input_dev->absbit);
 set_bit(ABS_MT_POSITION_Y, ps_data->ges_input_dev->absbit);
 set_bit(ABS_MT_WIDTH_MAJOR, ps_data->ges_input_dev->absbit);

 

 
 input_set_abs_params(ps_data->ges_input_dev,
        ABS_MT_POSITION_X, 0, 800, 0, 0);
 input_set_abs_params(ps_data->ges_input_dev,
        ABS_MT_POSITION_Y, 0, 600, 0, 0);
 input_set_abs_params(ps_data->ges_input_dev,
        ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
 input_set_abs_params(ps_data->ges_input_dev,
        ABS_MT_WIDTH_MAJOR, 0, 200, 0, 0);

 

 set_bit(EV_ABS, ps_data->ges_input_dev->evbit);
 set_bit(EV_KEY, ps_data->ges_input_dev->evbit);
 
 // test
 set_bit(BTN_TOUCH, ps_data->ges_input_dev->keybit);  
 input_set_abs_params(ps_data->ges_input_dev, ABS_X,
   0, 800, 4, 0);
 input_set_abs_params(ps_data->ges_input_dev, ABS_Y,
   0, 900, 4, 0); 
#endif
 
    ret = input_register_device(ps_data->ges_input_dev);
    if (ret<0) {
        printk("%s: can not register ges input device\n", __func__);
        return ret;
    }
/*
    ret = sysfs_create_group(&ps_data->ges_input_dev->dev.kobj, &stk_dae_attribute_group);
    if (ret < 0) {
        printk("%s:could not create sysfs group for ges\n", __func__);
        return ret;
    }
 
    input_set_drvdata(ps_data->ges_input_dev, ps_data);
 */
 
    ps_data->dae_input_dev = input_allocate_device();
    if (ps_data->dae_input_dev==NULL) {
        printk("%s: could not allocate dae device\n", __func__);
        ret = -ENOMEM;
        return ret;
    }
    ps_data->dae_input_dev->name = DAE_NAME;
    //ps_data->dae_input_dev->evbit[0] = BIT_MASK(EV_KEY);
 input_set_capability(ps_data->dae_input_dev, EV_REL, REL_X);
 input_set_capability(ps_data->dae_input_dev, EV_REL, REL_Y);
 input_set_capability(ps_data->dae_input_dev, EV_REL, REL_Z);
 input_set_capability(ps_data->dae_input_dev, EV_REL, REL_MISC); 
    ret = input_register_device(ps_data->dae_input_dev);
    if (ret<0) {
        printk("%s: can not register dae input device\n", __func__);
        return ret;
    }

 

    ret = sysfs_create_group(&ps_data->dae_input_dev->dev.kobj, &stk_dae_attribute_group);
    if (ret < 0) {
        printk("%s:could not create sysfs group for dae\n", __func__);
        return ret;
    }
    input_set_drvdata(ps_data->dae_input_dev, ps_data); 
 
    return 0;
}

 

static void stk_del_input_devices(struct stk3420_data *ps_data)
{
    sysfs_remove_group(&ps_data->dae_input_dev->dev.kobj, &stk_dae_attribute_group);
    input_unregister_device(ps_data->dae_input_dev);
    input_free_device(ps_data->dae_input_dev); 
    //sysfs_remove_group(&ps_data->ges_input_dev->dev.kobj, &stk_dae_attribute_group);
    input_unregister_device(ps_data->ges_input_dev);
    input_free_device(ps_data->ges_input_dev);
    sysfs_remove_group(&ps_data->ps_input_dev->dev.kobj, &stk_ps_attribute_group);
    sysfs_remove_group(&ps_data->als_input_dev->dev.kobj, &stk_als_attribute_group);
    input_unregister_device(ps_data->ps_input_dev);
    input_unregister_device(ps_data->als_input_dev);
    input_free_device(ps_data->ps_input_dev);
    input_free_device(ps_data->als_input_dev);
    return;
}

 

static void stk3420_proc_plat_data(struct stk3420_data *ps_data, struct stk3420_platform_data *plat_data)
{
    uint8_t w_reg = 0;

 

    ps_data->reg.state_reg = 0;
    ps_data->reg.psgsctrl1_reg = plat_data->psgsctrl1_reg;
    ps_data->reg.ledctrl_reg = plat_data->ledctrl_reg;
    ps_data->reg.alsctrl1_reg = plat_data->alsctrl1_reg;
    ps_data->reg.wait1_psgs_reg_ps = plat_data->wait1_psgs_reg_ps;
    ps_data->reg.wait1_psgs_reg_gs = plat_data->wait1_psgs_reg_gs;
    ps_data->reg.alsctrl2_reg = plat_data->alsctrl2_reg;
    ps_data->reg.psgsctrl2_reg = plat_data->psgsctrl2_reg;
    ps_data->reg.fifoctrl_reg = plat_data->fifoctrl_reg;
    ps_data->reg.wait_als_reg = plat_data->wait_als_reg;
    ps_data->reg.wait2_ps_reg = plat_data->wait2_ps_reg;

 

    if(ps_data->ps_thd_h == 0 && ps_data->ps_thd_l == 0) {
        ps_data->ps_thd_h = plat_data->ps_thd_h;
        ps_data->ps_thd_l = plat_data->ps_thd_l;
    }

 

#ifdef CALI_PS_EVERY_TIME
    ps_data->ps_high_thd_boot = plat_data->ps_thd_h;
    ps_data->ps_low_thd_boot = plat_data->ps_thd_l;
#endif

 

#ifndef STK_POLL_PS
    w_reg = (STK_PS_INT_MODE?STK_INT_PS_MODE_MASK:0) | STK_INT_PS_MASK; 
#endif

 

#if (!defined(STK_POLL_ALS) && (STK_PS_INT_MODE == 0x00) )
    w_reg |= STK_INT_ALS_MASK;
#endif
    ps_data->reg.int_reg = w_reg;
    return;
}

 

#endif

 

static int stk3420_probe(struct i2c_client *client,
                         const struct i2c_device_id *id)
{
 printk("%s: driver version = %s\n", __func__, DRIVER_VERSION);
#if 1
    int ret = -ENODEV;
    struct stk3420_data *ps_data;
    struct stk3420_platform_data *plat_data;
 
   

 

    if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
        printk("%s: No Support for I2C_FUNC_I2C\n", __func__);
        return -ENODEV;
    }

 

    ps_data = kzalloc(sizeof(struct stk3420_data),GFP_KERNEL);
    if(!ps_data) {
        printk("%s: failed to allocate stk3420_data\n", __func__);
        return -ENOMEM;
    }
    ps_data->client = client;
    i2c_set_clientdata(client,ps_data);
    mutex_init(&ps_data->io_lock);
    wake_lock_init(&ps_data->ps_wakelock,WAKE_LOCK_SUSPEND, "stk_input_wakelock");

 

#ifdef STK_POLL_PS
    wake_lock_init(&ps_data->ps_nosuspend_wl,WAKE_LOCK_SUSPEND,
                   "stk_nosuspend_wakelock");
#endif

 

    if (client->dev.of_node) {
        printk("%s: probe with device tree\n", __func__);
        plat_data = devm_kzalloc(&client->dev,
                                 sizeof(struct stk3420_platform_data), GFP_KERNEL);
        if (!plat_data) {
            printk("Failed to allocate memory\n");
            return -ENOMEM;
        }

 

        ret = stk_parse_dt(&client->dev, plat_data);
        if (ret) {
   printk("%s: stk_parse_dt ret=%d\n", __func__, ret);
            goto err_ps_data;
  }
    } else {
        printk("%s: probe with platform data\n", __func__);
#ifdef SPREADTRUM_PLATFORM
        plat_data = &stk3420_pfdata;
#else
        plat_data = client->dev.platform_data;
#endif  
    }
    if (!plat_data) {
        printk("%s: no stk3420 platform data!\n", __func__);
        goto err_ps_data;
    }
    ps_data->als_transmittance = plat_data->transmittance;
    //ps_data->int_number = plat_data->int_number;
 ps_data->int_number = ls_sensor_info.int_number;
    ps_data->pdata = plat_data;

 

    if (ps_data->als_transmittance == 0) {
        printk("%s: Please set als_transmittance\n", __func__);
        goto err_ps_data;
    }
 stk3420_proc_plat_data(ps_data, plat_data);
 
    stk_set_wq(ps_data);

 

    ps_data->tune0.stk_max_min_diff = STK_MAX_MIN_DIFF;
    ps_data->tune0.stk_lt_n_ct = STK_LT_N_CT;
    ps_data->tune0.stk_ht_n_ct = STK_HT_N_CT;

 


    ps_data->als_enabled = false;
    ps_data->ps_enabled = false;

 

 ret = stk3420_check_pid(ps_data);
    if(ret < 0)
        goto err_power_on;

 

//#ifndef QUALCOMM_PLATFORM
    ret = stk3420_init_all_setting(client, plat_data);
    if(ret < 0)
        goto err_power_on;

 

    ret = stk_ps_tune0_boot_init(ps_data);
    if(ret < 0)
        goto err_power_on;
//#endif  
    ret = stk_set_input_devices(ps_data);
    if(ret < 0)
        goto err_setup_input_device;

 

#if (!defined(STK_POLL_ALS) || !defined(STK_POLL_PS))
    ret = stk_setup_irq(client);
    if(ret < 0)
        goto err_setup_irq;
#endif
    device_init_wakeup(&client->dev, true);

 

//#ifdef CONFIG_HAS_EARLYSUSPEND

 

 

 

 

 


    printk("%s: probe successfully", __func__);
    return 0;

 


    device_init_wakeup(&client->dev, false);
#if (!defined(STK_POLL_ALS) || !defined(STK_POLL_PS))
err_setup_irq:
 free_irq(ps_data->irq, ps_data);
#ifdef SPREADTRUM_PLATFORM
    sprd_free_gpio_irq(ps_data->int_number);
#else
 if(gpio_is_valid(ps_data->int_number))
  gpio_free(ps_data->int_number);
#endif
#endif
err_setup_input_device:
    stk_del_input_devices(ps_data);
err_power_on:

 

err_power_init:
    stk_del_wq(ps_data);
err_ps_data:
#ifdef STK_POLL_PS
    wake_lock_destroy(&ps_data->ps_nosuspend_wl);
#endif
    wake_lock_destroy(&ps_data->ps_wakelock);
    mutex_destroy(&ps_data->io_lock);
    kfree(ps_data);
    return ret;
#endif
}

 


static int stk3420_remove(struct i2c_client *client)
{
#if 1
    struct stk3420_data *ps_data = i2c_get_clientdata(client);

 

    device_init_wakeup(&client->dev, false);
#if (!defined(STK_POLL_ALS) || !defined(STK_POLL_PS))
    free_irq(ps_data->irq, ps_data);
#ifdef SPREADTRUM_PLATFORM
    sprd_free_gpio_irq(ps_data->int_number);
#else
 if(gpio_is_valid(ps_data->int_number))
  gpio_free(ps_data->int_number);
#endif
#endif
    stk_del_input_devices(ps_data);

 

    stk_del_wq(ps_data);
#ifdef STK_POLL_PS
    wake_lock_destroy(&ps_data->ps_nosuspend_wl);
#endif
    wake_lock_destroy(&ps_data->ps_wakelock);
    mutex_destroy(&ps_data->io_lock);
    kfree(ps_data);

 

    return 0;
#endif
}

 

static int ls_detect(struct i2c_client *client, struct i2c_board_info *info)
{
 struct i2c_adapter *adapter = client->adapter;
    if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
                return -ENODEV;
     if(ls_sensor_info.twi_id == adapter->nr){
            printk("%s: addr= %x\n",__func__,client->addr);
   strlcpy(info->type, DEVICE_NAME, I2C_NAME_SIZE);
   return 0;

 

 }else{
  return -ENODEV;
 }
}

 

static const struct i2c_device_id stk_ps_id[] = {
    { "stk3420", 0},
    {}
};

 

MODULE_DEVICE_TABLE(i2c, stk_ps_id);

 

#if 0
static struct of_device_id stk_match_table[] = {
    { .compatible = "stk3420", },
    { },
};
#endif

 


static struct i2c_driver stk_ps_driver = {
    .driver = {
        .name = DEVICE_NAME, //名字与sysconfig.fex中light_sensor的名字匹配
        .owner = THIS_MODULE,
#ifdef CONFIG_OF
        //.of_match_table = stk_match_table,
#endif
        .pm = &stk3420_pm_ops,
    },
    .probe = stk3420_probe,
    .remove = stk3420_remove,
    .id_table = stk_ps_id,
 .class = I2C_CLASS_HWMON,
 .detect  = ls_detect,
 .address_list   = normal_i2c, //地址与sysconfig.fex中light_sensor的I2C地址匹配
};

 


//static int __init stk3420_init(void)
static int stk3420_init(void)
{
    int ret;
 printk("%s:light sensor drive init\n",__func__);
 #if 1
 if (input_fetch_sysconfig_para(&(ls_sensor_info.input_type))) {
  printk("%s: ls_fetch_sysconfig_para err.\n", __func__);
  return 0;
 } else {
  ret = input_init_platform_resource(&(ls_sensor_info.input_type));
 if (0 != ret) {
   printk("%s:ls_init_platform_resource err. \n", __func__);   
  }
 }

 

 if (ls_sensor_info.sensor_used == 0) {
  printk("*** ls_used set to 0 !\n");
  printk("*** if use light_sensor,please put the sys_config.fex ls_used set to 1. \n");
  return 0;
 }
 #endif
 #if 1
    ret = i2c_add_driver(&stk_ps_driver);
    if (ret) {
        i2c_del_driver(&stk_ps_driver);
        return ret;
    }
 #endif
    return 0;
}

 

static void stk3420_exit(void)
{
    i2c_del_driver(&stk_ps_driver);
}

 

module_init(stk3420_init);
module_exit(stk3420_exit);
MODULE_DESCRIPTION("Sensortek stk3420 Sensor driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRIVER_VERSION);

 

//-------------------------------------------------------

 

配置Makefile 模块编译,同时在android\device\softwinner\astar-m86\init.sun8i.rc 里的modules下添加使开机自动加载

 

//-------------------------------------------------------
编译烧录,通过adb 进入根文件系统 adb shell getevent看设备节点有没有出来
adb shell 后cd /sys/class/input/event5/device/ -> echo 1 > enable后,手在距感上方看有没有数据上报(getevent 下的数据上报情况),如果有说明底层调通了,没有问题,
如果没有则需再检查驱动,
确定底层调通后,剩下就是hal层了
//-------------------------------------------------------
在android\device\softwinner\astar-m86\init.sun8i.rc 里的sys下
 chmod 0666 /sys/class/input/input4/cali ;//改变文件(/sys/class/input/input4/cali)的使用权限为0660
 chown system system /sys/class/input/input4/enable   //改变目录(/sys/class/input/input4/enable)的使用群体为system (距感)
 chmod 0666 /sys/class/input/input5/cali
 chown system system /sys/class/input/input5/enable  //(光感)
//-------------------------------------------------------
合入hal层代码到下面目录
androidM/device/softwinner/polaris-common/hardware/libhardware/libsensors/
包括 LightSensor.cpp,ProximitySensor.cpp,InputEventReader.cpp,SensorBase.cpp,sensors.cpp
编译烧录后,再adb install lightsensor.apk 在apk里android button下,打开ps_on(给距感的enable写1下来),手在距感上方看有没有数据上报(getevent 下的数据上报情况)

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zeropoint127

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值