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 下的数据上报情况)