diff options
| author | Yuval Adam <_@yuv.al> | 2017-08-30 08:25:59 +0000 |
|---|---|---|
| committer | Yuval Adam <_@yuv.al> | 2017-08-30 08:25:59 +0000 |
| commit | 8e4bff4cab0ddac6060645b0715210484d02ff40 (patch) | |
| tree | 3a5c3024371a04692a3a6d9974d001cdff8ebf84 /drivers/input/misc/tmd2771_pls.c | |
Diffstat (limited to 'drivers/input/misc/tmd2771_pls.c')
| -rw-r--r-- | drivers/input/misc/tmd2771_pls.c | 1591 |
1 files changed, 1591 insertions, 0 deletions
diff --git a/drivers/input/misc/tmd2771_pls.c b/drivers/input/misc/tmd2771_pls.c new file mode 100644 index 00000000..e3cc465e --- /dev/null +++ b/drivers/input/misc/tmd2771_pls.c @@ -0,0 +1,1591 @@ +/******************************************************************************* +* * +* File Name: taos.c * +* Description: Linux device driver for Taos ambient light and * +* proximity sensors. * +* Author: John Koshi * +* History: 09/16/2009 - Initial creation * +* 10/09/2009 - Triton version * +* 12/21/2009 - Probe/remove mode * +* 02/07/2010 - Add proximity * +* * +******************************************************************************** +* Proprietary to Taos Inc., 1001 Klein Road #300, Plano, TX 75074 * +*******************************************************************************/ +// includes +#include <linux/kernel.h> +#include <linux/fs.h> +#include <linux/cdev.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/i2c.h> +#include <linux/hwmon.h> +#include <linux/timer.h> +#include <asm/uaccess.h> +#include <asm/errno.h> +#include <asm/delay.h> +#include <linux/i2c/tmd2771_pls.h> +#include <linux/delay.h> +//iVIZM +#include <linux/irq.h> +#include <linux/interrupt.h> +#include <linux/slab.h> +#include <mach/gpio.h> +#include <linux/poll.h> +#include <linux/wakelock.h> +#include <linux/input.h> +#include <linux/regulator/consumer.h> +#include <mach/regulator.h> + +#include <linux/miscdevice.h> + +// device name/id/address/counts +#define TAOS_DEVICE_NAME "tmd2771_pls" +#define TAOS_DEVICE_ID "tritonFN" +#define TAOS_ID_NAME_SIZE 10 +#define TAOS_TRITON_CHIPIDVAL 0x00 +#define TAOS_TRITON_MAXREGS 32 +#define TAOS_DEVICE_ADDR1 0x29 +#define TAOS_DEVICE_ADDR2 0x39 +#define TAOS_DEVICE_ADDR3 0x49 +#define TAOS_MAX_NUM_DEVICES 3 +#define TAOS_MAX_DEVICE_REGS 32 +#define I2C_MAX_ADAPTERS 8 + +// TRITON register offsets +#define TAOS_TRITON_CNTRL 0x00 +#define TAOS_TRITON_ALS_TIME 0X01 +#define TAOS_TRITON_PRX_TIME 0x02 +#define TAOS_TRITON_WAIT_TIME 0x03 +#define TAOS_TRITON_ALS_MINTHRESHLO 0X04 +#define TAOS_TRITON_ALS_MINTHRESHHI 0X05 +#define TAOS_TRITON_ALS_MAXTHRESHLO 0X06 +#define TAOS_TRITON_ALS_MAXTHRESHHI 0X07 +#define TAOS_TRITON_PRX_MINTHRESHLO 0X08 +#define TAOS_TRITON_PRX_MINTHRESHHI 0X09 +#define TAOS_TRITON_PRX_MAXTHRESHLO 0X0A +#define TAOS_TRITON_PRX_MAXTHRESHHI 0X0B +#define TAOS_TRITON_INTERRUPT 0x0C +#define TAOS_TRITON_PRX_CFG 0x0D +#define TAOS_TRITON_PRX_COUNT 0x0E +#define TAOS_TRITON_GAIN 0x0F +#define TAOS_TRITON_REVID 0x11 +#define TAOS_TRITON_CHIPID 0x12 +#define TAOS_TRITON_STATUS 0x13 +#define TAOS_TRITON_ALS_CHAN0LO 0x14 +#define TAOS_TRITON_ALS_CHAN0HI 0x15 +#define TAOS_TRITON_ALS_CHAN1LO 0x16 +#define TAOS_TRITON_ALS_CHAN1HI 0x17 +#define TAOS_TRITON_PRX_LO 0x18 +#define TAOS_TRITON_PRX_HI 0x19 +#define TAOS_TRITON_TEST_STATUS 0x1F + +// Triton cmd reg masks +#define TAOS_TRITON_CMD_REG 0X80 +#define TAOS_TRITON_CMD_AUTO 0x10 //iVIZM +#define TAOS_TRITON_CMD_BYTE_RW 0x00 +#define TAOS_TRITON_CMD_WORD_BLK_RW 0x20 +#define TAOS_TRITON_CMD_SPL_FN 0x60 +#define TAOS_TRITON_CMD_PROX_INTCLR 0X05 +#define TAOS_TRITON_CMD_ALS_INTCLR 0X06 +#define TAOS_TRITON_CMD_PROXALS_INTCLR 0X07 +#define TAOS_TRITON_CMD_TST_REG 0X08 +#define TAOS_TRITON_CMD_USER_REG 0X09 + +// Triton cntrl reg masks +#define TAOS_TRITON_CNTL_PROX_INT_ENBL 0X20 +#define TAOS_TRITON_CNTL_ALS_INT_ENBL 0X10 +#define TAOS_TRITON_CNTL_WAIT_TMR_ENBL 0X08 +#define TAOS_TRITON_CNTL_PROX_DET_ENBL 0X04 +#define TAOS_TRITON_CNTL_ADC_ENBL 0x02 +#define TAOS_TRITON_CNTL_PWRON 0x01 + +// Triton status reg masks +#define TAOS_TRITON_STATUS_ADCVALID 0x01 +#define TAOS_TRITON_STATUS_PRXVALID 0x02 +#define TAOS_TRITON_STATUS_ADCINTR 0x10 +#define TAOS_TRITON_STATUS_PRXINTR 0x20 + +// lux constants +#define TAOS_MAX_LUX 10000 +#define TAOS_SCALE_MILLILUX 3 +#define TAOS_FILTER_DEPTH 3 +#define CHIP_ID 0x3d + +#define TAOS_INPUT_NAME "light sensor" +// forward declarations +static int taos_probe(struct i2c_client *clientp, const struct i2c_device_id *idp); +static int taos_remove(struct i2c_client *client); +static int taos_open(struct inode *inode, struct file *file); +static int taos_release(struct inode *inode, struct file *file); +static int taos_ioctl(struct file *file, unsigned int cmd, unsigned long arg); +static int taos_get_lux(void); +//static int taos_lux_filter(int raw_lux); +static int taos_device_name(unsigned char *bufp, char **device_name); +static int taos_prox_poll(struct taos_prox_info *prxp); +static void taos_prox_poll_timer_func(unsigned long param); +static void taos_prox_poll_timer_start(void); +//iVIZM +static int taos_als_threshold_set(void); +static int taos_prox_threshold_set(void); +static int taos_als_get_data(void); +static int taos_interrupts_clear(void); +//static unsigned int taos_poll(struct file *filp, poll_table *wait); +//static int taos_resume(struct i2c_client *client); +//static int taos_suspend(struct i2c_client *client,pm_message_t mesg); + + +DECLARE_WAIT_QUEUE_HEAD(waitqueue_read);//iVIZM + +#define ALS_PROX_DEBUG //iVIZM + +// first device number +static dev_t taos_dev_number; + +// workqueue struct +//static struct workqueue_struct *taos_wq; //iVIZM + +// class structure for this device +struct class *taos_class; + +// module device table +static struct i2c_device_id taos_idtable[] = { + {TAOS_DEVICE_NAME, 0}, + {} +}; +MODULE_DEVICE_TABLE(i2c, taos_idtable); + +// board and address info iVIZM +struct i2c_board_info taos_board_info[] = { + {I2C_BOARD_INFO(TAOS_DEVICE_ID, TAOS_DEVICE_ADDR2),}, +}; + +unsigned short const taos_addr_list[2] = {TAOS_DEVICE_ADDR2, I2C_CLIENT_END};//iVIZM + +// client and device +struct i2c_client *my_clientp; +struct i2c_client *bad_clientp[TAOS_MAX_NUM_DEVICES]; +static int num_bad = 0; +static int device_found = 0; +//iVIZM +static char pro_buf[4]; //iVIZM +static int mcount = 0; //iVIZM +static char als_buf[4]; //iVIZM +u16 status = 0; +static int ALS_ON; + +// driver definition +static struct i2c_driver taos_driver = { + .driver = { + .owner = THIS_MODULE, + .name = TAOS_DEVICE_NAME, + }, + .id_table = taos_idtable, + .probe = taos_probe, + //.resume = taos_resume,//iVIZM + //.suspend = taos_suspend,//iVIZM + .remove = __devexit_p(taos_remove), +}; + +// per-device data +struct taos_data { + struct i2c_client *client; + struct cdev cdev; + unsigned int addr; + struct input_dev *input_dev;//iVIZM + struct work_struct work;//iVIZM + struct wake_lock taos_wake_lock;//iVIZM + char taos_id; + char taos_name[TAOS_ID_NAME_SIZE]; + struct semaphore update_lock; + char valid; + //int working; + unsigned long last_updated; + struct regulator *reg_vdd; +} *taos_datap; + +// file operations +static struct file_operations taos_fops = { + .owner = THIS_MODULE, + .open = taos_open, + .release = taos_release, + .unlocked_ioctl = taos_ioctl, +}; + +// device configuration +struct taos_cfg *taos_cfgp; + +#if 1 //zwj add +static struct file_operations taos_fops_2 = { + .owner = THIS_MODULE, + .open = taos_open, + .release = taos_release, + .unlocked_ioctl = taos_ioctl, +}; + +static struct miscdevice taos_device = { + .minor = MISC_DYNAMIC_MINOR, + .name = TAOS_DEVICE_NAME, + .fops = &taos_fops_2, +}; +#endif + + +static u32 calibrate_target_param = 300000; +static u16 als_time_param = 200; +static u16 scale_factor_param = 1; +static u16 gain_trim_param = 512; +static u8 filter_history_param = 3; +static u8 filter_count_param = 1; +static u8 gain_param = 2; +static u16 prox_threshold_hi_param = 560; //120; +static u16 prox_threshold_lo_param = 500; //80; +static u16 als_threshold_hi_param = 3000;//iVIZM +static u16 als_threshold_lo_param = 10;//iVIZM +static u8 prox_int_time_param = 0xEE;//50ms +static u8 prox_adc_time_param = 0xFF; +static u8 prox_wait_time_param = 0xEE; +static u8 prox_intr_filter_param = 0x23; +static u8 prox_config_param = 0x00; +static u8 prox_pulse_cnt_param = 0x04; //0x01; +static u8 prox_gain_param = 0xA2; //0x22; + +// prox info +struct taos_prox_info prox_cal_info[20]; +struct taos_prox_info prox_cur_info; +struct taos_prox_info *prox_cur_infop = &prox_cur_info; +static u8 prox_history_hi = 0; +static u8 prox_history_lo = 0; +static struct timer_list prox_poll_timer; +static int prox_on = 0; +static int device_released = 0; +static u16 sat_als = 0; +static u16 sat_prox = 0; + +// device reg init values +u8 taos_triton_reg_init[16] = {0x00,0xFF,0XFF,0XFF,0X00,0X00,0XFF,0XFF,0X00,0X00,0XFF,0XFF,0X00,0X00,0X00,0X00}; + +// lux time scale +struct time_scale_factor { + u16 numerator; + u16 denominator; + u16 saturation; +}; +struct time_scale_factor TritonTime = {1, 0, 0}; +struct time_scale_factor *lux_timep = &TritonTime; + +// gain table +u8 taos_triton_gain_table[] = {1, 8, 16, 120}; + +// lux data + +struct lux_data { + u16 ratio; + u16 clear; + u16 ir; + +}; +struct lux_data TritonFN_lux_data[] = { + { 9830, 8320, 15360 }, + { 12452, 10554, 22797 }, + { 14746, 6234, 11430 }, + { 17695, 3968, 6400 }, + { 0, 0, 0 } +}; +struct lux_data *lux_tablep = TritonFN_lux_data; +static int lux_history[TAOS_FILTER_DEPTH] = {-ENODATA, -ENODATA, -ENODATA};//iVIZM + +static int tmd2711_pls_irq; + + + +static irqreturn_t taos_irq_handler(int irq, void *dev_id) //iVIZM +{ + //disable_irq_nosync(tmd2711_pls_irq); + //queue_work(taos_wq,&taos_datap->work); + //printk("^^^^^^^^^^^^^^^^^^ taos_irq_handler ^^^^^^^^^^^^^^^^^^^^\n"); + schedule_work(&taos_datap->work); + //enable_irq(tmd2711_pls_irq); + + return IRQ_HANDLED; +} + +static int taos_get_data(void)//iVIZM +{ + int ret = 0; + + //printk("^^^^^^^^^^^^^^^^^^ taos_get_data ^^^^^^^^^^^^^^^^^^^^\n"); + + if ((ret = (i2c_smbus_write_byte(taos_datap->client, (TAOS_TRITON_CMD_REG | 0x13)))) < 0) { + //printk(KERN_ERR "TAOS: i2c_smbus_write_byte(1) failed in taos_work_func()\n"); + return (ret); + } + status = i2c_smbus_read_byte(taos_datap->client); + // if (down_interruptible(&taos_datap->update_lock)) + // return -ERESTARTSYS; + printk(" kl# %s, line=%d, status=%x\n", __func__, __LINE__, status); + // status : 5:4 = pint:aint //It has a little error here + // 1:1 = pint:aint + // 1:0 = pint + // 0:1 = aint + if((status & 0x20) == 0x20) { // ps + ret = taos_prox_threshold_set(); + } else if((status & 0x10) == 0x10) { // as + taos_als_threshold_set(); + taos_als_get_data(); + } + //up(&taos_datap->update_lock); + return ret; +} + +static int taos_interrupts_clear(void)//iVIZM +{ + int ret = 0; + if ((ret = (i2c_smbus_write_byte(taos_datap->client, (TAOS_TRITON_CMD_REG|TAOS_TRITON_CMD_SPL_FN|0x07)))) < 0) { + //printk(KERN_ERR "TAOS: i2c_smbus_write_byte(2) failed in taos_work_func()\n"); + return (ret); + } + return ret; +} +static void taos_work_func(struct work_struct * work) //iVIZM +{ + wake_lock(&taos_datap->taos_wake_lock); + printk("^^^^^^^^^^^^^^^^^^ taos_work_func ^^^^^^^^^^^^^^^^^^^^\n"); + taos_get_data(); + taos_interrupts_clear(); + wake_unlock(&taos_datap->taos_wake_lock); +} + +static int taos_als_get_data(void)//iVIZM +{ + int ret = 0; + u8 reg_val; + int lux_val = 0; + if ((ret = (i2c_smbus_write_byte(taos_datap->client, (TAOS_TRITON_CMD_REG | TAOS_TRITON_CNTRL)))) < 0) { + //printk(KERN_ERR "TAOS: i2c_smbus_write_byte failed in ioctl als_data\n"); + return (ret); + } + reg_val = i2c_smbus_read_byte(taos_datap->client); + if ((reg_val & (TAOS_TRITON_CNTL_ADC_ENBL | TAOS_TRITON_CNTL_PWRON)) != (TAOS_TRITON_CNTL_ADC_ENBL | TAOS_TRITON_CNTL_PWRON)) + return -ENODATA; + if ((ret = (i2c_smbus_write_byte(taos_datap->client, (TAOS_TRITON_CMD_REG | TAOS_TRITON_STATUS)))) < 0) { + //printk(KERN_ERR "TAOS: i2c_smbus_write_byte failed in ioctl als_data\n"); + return (ret); + } + reg_val = i2c_smbus_read_byte(taos_datap->client); + if ((reg_val & TAOS_TRITON_STATUS_ADCVALID) != TAOS_TRITON_STATUS_ADCVALID) + return -ENODATA; + if ((lux_val = taos_get_lux()) < 0) + printk(KERN_ERR "TAOS: call to taos_get_lux() returned error %d in ioctl als_data\n", lux_val); + printk("********** before taos_als_get_data ********* lux_val = %d \n",lux_val); + input_report_abs(taos_datap->input_dev,ABS_MISC,lux_val); + input_sync(taos_datap->input_dev); // zwj add test + return ret; +} + + +static int taos_als_threshold_set(void)//iVIZM +{ + int i,ret = 0; + u8 chdata[2]; + u16 ch0; + + printk("kl# %s, line=%d \n", __func__, __LINE__); + + for (i = 0; i < 2; i++) { + chdata[i] = (i2c_smbus_read_byte_data(taos_datap->client, (TAOS_TRITON_CMD_REG | TAOS_TRITON_CMD_WORD_BLK_RW | (TAOS_TRITON_ALS_CHAN0LO + i)))); + } + ch0 = chdata[0] + chdata[1]*256; + als_threshold_hi_param = (12*ch0)/10; + if (als_threshold_hi_param >= 65535) + als_threshold_hi_param = 65535; + als_threshold_lo_param = (8*ch0)/10; + als_buf[0] = als_threshold_lo_param & 0x0ff; + als_buf[1] = als_threshold_lo_param >> 8; + als_buf[2] = als_threshold_hi_param & 0x0ff; + als_buf[3] = als_threshold_hi_param >> 8; + + for( mcount=0; mcount<4; mcount++ ) { + if ((ret = (i2c_smbus_write_byte_data(taos_datap->client, (TAOS_TRITON_CMD_REG|0x04) + mcount, als_buf[mcount]))) < 0) { + //printk(KERN_ERR "TAOS: i2c_smbus_write_byte_data failed in taos als threshold set\n"); + return (ret); + } + } + return ret; +} + +static int taos_prox_threshold_set(void)//iVIZM +{ + int i,ret = 0; + u8 chdata[6]; + u16 proxdata = 0; + u16 cleardata = 0; + int data = 0; + + // int ch0,ch1; +// printk("kl# %s, line=%d \n", __func__, __LINE__); + + for (i = 0; i < 6; i++) { + chdata[i] = (i2c_smbus_read_byte_data(taos_datap->client, (TAOS_TRITON_CMD_REG | TAOS_TRITON_CMD_WORD_BLK_RW| (TAOS_TRITON_ALS_CHAN0LO + i)))); + } + cleardata = chdata[0] + chdata[1]*256; + proxdata = chdata[4] + chdata[5]*256; + printk("kl## = proxdata = %d, cleardata=%d\n",proxdata, cleardata); + + //ch0= i2c_smbus_read_byte_data(taos_datap->client, (TAOS_TRITON_CMD_REG | 0x18 )); + //ch1= i2c_smbus_read_byte_data(taos_datap->client, (TAOS_TRITON_CMD_REG | 0x19 )); + + //printk("================= proxdatatest = %d\n",ch1<<8 |ch0); + + if(prox_on || (proxdata < (taos_cfgp->prox_threshold_lo ))) + { + pro_buf[0] = 0x0; + pro_buf[1] = 0x0; + pro_buf[2] = taos_cfgp->prox_threshold_hi & 0x0ff; + pro_buf[3] = taos_cfgp->prox_threshold_hi >> 8; + data = 1; + printk(KERN_ERR "report pls data 1\n"); + input_report_abs(taos_datap->input_dev,ABS_DISTANCE,data); + input_sync(taos_datap->input_dev); + } + else if(proxdata > (taos_cfgp->prox_threshold_hi) ) + { + if (cleardata > ((sat_als*80)/100)){ + data = 0; + } + else{ + pro_buf[0] = taos_cfgp->prox_threshold_lo & 0x0ff; + pro_buf[1] = taos_cfgp->prox_threshold_lo >> 8; + pro_buf[2] = 0xff; + pro_buf[3] = 0xff; + data = 0; + } + input_report_abs(taos_datap->input_dev,ABS_DISTANCE,data); + + input_sync(taos_datap->input_dev); + } + + // printk("prox_threshold_hi=%d, prox_threshold_lo= %d\n",pro_buf[3]<<8 |pro_buf[2], pro_buf[1]<<8 |pro_buf[0]); + + for( mcount=0; mcount<4; mcount++ ) { + if ((ret = (i2c_smbus_write_byte_data(taos_datap->client, (TAOS_TRITON_CMD_REG|0x08) + mcount, pro_buf[mcount]))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte_data failed in taos prox threshold set\n"); + return (ret); + } + } + + prox_on = 0; + return ret; +} + +static int taos_reg_init(struct i2c_client *clientp) +{ + int ret = 0; + int i = 0; + unsigned char buf[TAOS_MAX_DEVICE_REGS]; + char *device_name; + int chip_id; + + for (i = 0; i < TAOS_MAX_DEVICE_REGS; i++) { + if ((ret = (i2c_smbus_write_byte(clientp, (TAOS_TRITON_CMD_REG | (TAOS_TRITON_CNTRL + i))))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte() to control reg failed in taos_probe()\n"); + return(ret); + } + buf[i] = i2c_smbus_read_byte(clientp); + } + if ((ret = taos_device_name(buf, &device_name)) == 0) { + printk(KERN_ERR "TAOS: chip id that was read found mismatched by taos_device_name(), in taos_probe()\n"); + return -ENODEV; + } + if (strcmp(device_name, TAOS_DEVICE_ID)) { + printk(KERN_ERR "TAOS: chip id that was read does not match expected id in taos_probe()\n"); + return -ENODEV; + } + else { + printk(KERN_ERR "TAOS: chip id of %s that was read matches expected id in taos_probe()\n", device_name); + device_found = 1; + } + if ((ret = (i2c_smbus_write_byte(clientp, (TAOS_TRITON_CMD_REG | TAOS_TRITON_CNTRL)))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte() to control reg failed in taos_probe()\n"); + return(ret); + } + strlcpy(clientp->name, TAOS_DEVICE_ID, I2C_NAME_SIZE); + strlcpy(taos_datap->taos_name, TAOS_DEVICE_ID, TAOS_ID_NAME_SIZE); + taos_datap->valid = 0; + if (!(taos_cfgp = kmalloc(sizeof(struct taos_cfg), GFP_KERNEL))) { + printk(KERN_ERR "TAOS: kmalloc for struct taos_cfg failed in taos_probe()\n"); + return -ENOMEM; + } + taos_cfgp->calibrate_target = calibrate_target_param; + taos_cfgp->als_time = als_time_param; + taos_cfgp->scale_factor = scale_factor_param; + taos_cfgp->gain_trim = gain_trim_param; + taos_cfgp->filter_history = filter_history_param; + taos_cfgp->filter_count = filter_count_param; + taos_cfgp->gain = gain_param; + taos_cfgp->als_threshold_hi = als_threshold_hi_param;//iVIZM + taos_cfgp->als_threshold_lo = als_threshold_lo_param;//iVIZM + taos_cfgp->prox_threshold_hi = prox_threshold_hi_param; + taos_cfgp->prox_threshold_lo = prox_threshold_lo_param; + taos_cfgp->prox_int_time = prox_int_time_param; + taos_cfgp->prox_adc_time = prox_adc_time_param; + taos_cfgp->prox_wait_time = prox_wait_time_param; + taos_cfgp->prox_intr_filter = prox_intr_filter_param; + taos_cfgp->prox_config = prox_config_param; + taos_cfgp->prox_pulse_cnt = prox_pulse_cnt_param; + taos_cfgp->prox_gain = prox_gain_param; + sat_als = (256 - taos_cfgp->prox_int_time) << 10; + sat_prox = (256 - taos_cfgp->prox_adc_time) << 10; + + /*dmobile ::power down for init ,Rambo liu*/ + printk("Rambo::light sensor will pwr down \n"); + if ((ret = (i2c_smbus_write_byte_data(taos_datap->client, (TAOS_TRITON_CMD_REG|0x00), 0x00))) < 0) { + printk(KERN_ERR "TAOS:Rambo, i2c_smbus_write_byte_data failed in power down\n"); + return (ret); + } +} + +static void tmd2771_pls_pininit(int irq_pin) +{ + printk(KERN_INFO "%s [irq=%d]\n",__func__,irq_pin); + gpio_request(irq_pin, "tmd2771_pls irq"); + gpio_direction_input(irq_pin); +} + + +// client probe +static int taos_probe(struct i2c_client *clientp, const struct i2c_device_id *idp) { + int ret = 0; + int i = 0; + int chip_id; + int ch0,ch1,ch2,ch3,ch4,ch5; + struct regulator *reg_vdd; + //unsigned char buf[TAOS_MAX_DEVICE_REGS]; + //char *device_name; + struct i2c_adapter *adapter = to_i2c_adapter(clientp->dev.parent); + struct tmd2771_pls_platform_data *pdata = clientp->dev.platform_data; + + printk("kl# tmd2771 probe!!!!line=%d\n", __LINE__); + + //reg_vdd = regulator_get(NULL,REGU_NAMES_VDD28); + //regulator_enable(reg_vdd); + + if (!i2c_check_functionality(clientp->adapter, I2C_FUNC_I2C)) { + printk("%s: functionality check failed\n", __func__); + ret = -ENODEV; + goto exit_check_functionality_failed; + } + + taos_datap = kmalloc(sizeof(struct taos_data), GFP_KERNEL); + if (!taos_datap) { + printk(KERN_ERR "TAOS: kmalloc for struct taos_data failed in taos_init()\n"); + //return -ENOMEM; + ret = -ENOMEM; + goto exit_request_memory_failed; + } + memset(taos_datap, 0, sizeof(struct taos_data)); + taos_datap->reg_vdd = reg_vdd; + + // get chip id + chip_id = i2c_smbus_read_byte_data(clientp, (TAOS_TRITON_CMD_REG | (TAOS_TRITON_CNTRL + 0x12))); //iVIZM + printk(" toas1 chip_id = %d\n",chip_id); + if(chip_id < 0) { + ret = chip_id; + goto exit_request_memory_failed; + } + + tmd2771_pls_pininit(pdata->irq_gpio_number); + + + /*get irq*/ + clientp->irq = gpio_to_irq(pdata->irq_gpio_number); + + tmd2711_pls_irq = clientp->irq; + + + taos_datap->client = clientp; + i2c_set_clientdata(clientp, taos_datap); + INIT_WORK(&(taos_datap->work),taos_work_func); + mutex_init(&taos_datap->update_lock); + + // input devices + taos_datap->input_dev = input_allocate_device();//iVIZM + if (taos_datap->input_dev == NULL) { + ret = -ENOMEM; + goto exit_input_dev_allocate_failed; + } + + taos_datap->input_dev->name = TAOS_INPUT_NAME; + taos_datap->input_dev->id.bustype = BUS_I2C; + set_bit(EV_ABS,taos_datap->input_dev->evbit); + set_bit(ABS_MISC, taos_datap->input_dev->absbit); + set_bit(ABS_DISTANCE, taos_datap->input_dev->absbit); + /*for proximity*/ + input_set_abs_params(taos_datap->input_dev, ABS_DISTANCE, 0, 1, 0, 0); + /*for lightsensor*/ + input_set_abs_params(taos_datap->input_dev, ABS_MISC, 0, 100001, 0, 0); + + ret = input_register_device(taos_datap->input_dev); + if (ret < 0) { + printk("%s: input device regist failed\n", __func__); + goto exit_input_register_failed; + } + // chip init + if(taos_reg_init(clientp)<0) + { + printk("%s: device init failed\n", __func__); + ret=-1; + goto exit_device_init_failed; + } + + // create char device + if ((ret = (alloc_chrdev_region(&taos_dev_number, 0, TAOS_MAX_NUM_DEVICES, TAOS_DEVICE_NAME))) < 0) { + printk(KERN_ERR "TAOS: alloc_chrdev_region() failed in taos_init()\n"); + goto exit_chrdev_region_failed; + } + taos_class = class_create(THIS_MODULE, TAOS_DEVICE_NAME); + cdev_init(&taos_datap->cdev, &taos_fops); + taos_datap->cdev.owner = THIS_MODULE; + if ((ret = (cdev_add(&taos_datap->cdev, taos_dev_number, 1))) < 0) { + printk(KERN_ERR "TAOS: cdev_add() failed in taos_init()\n"); + goto exit_chrdev_add_failed; + } + wake_lock_init(&taos_datap->taos_wake_lock, WAKE_LOCK_SUSPEND, "taos-wake-lock"); + device_create(taos_class, NULL, MKDEV(MAJOR(taos_dev_number), 0), &taos_driver ,"taos"); + + + + // interrupt + ret = request_irq(tmd2711_pls_irq,taos_irq_handler, IRQ_TYPE_EDGE_FALLING, "taos_irq",taos_datap);//iVIZM + if (ret != 0) { + goto irq_request_err; + } + disable_irq(tmd2711_pls_irq);//iVIZM + for(i = 0; i < 50; i++) + taos_als_get_data(); + + printk("%s probe success!\n", __func__); + return (ret); + +irq_request_err: + device_destroy(taos_class, MKDEV(MAJOR(taos_dev_number), 0)); + gpio_free(pdata->irq_gpio_number); +exit_chrdev_add_failed: + cdev_del(&taos_datap->cdev); + class_destroy(taos_class); +exit_chrdev_region_failed: + unregister_chrdev_region(taos_dev_number, TAOS_MAX_NUM_DEVICES); +exit_device_init_failed: +exit_input_register_failed: + input_free_device(taos_datap->input_dev); +exit_input_dev_allocate_failed: +exit_device_register_failed: + kfree(taos_datap); +exit_request_memory_failed: +exit_check_functionality_failed: + //wake_lock_destroy(&pls_delayed_work_wake_lock); + printk("kl %s: Probe Fail!\n",__func__); + return ret; +} +# if 0 +//resume iVIZM +static int taos_resume(struct i2c_client *client) { + u8 reg_val = 0,reg_cntrl = 0; + int ret = -1; + if ((ret = (i2c_smbus_write_byte(taos_datap->client, (TAOS_TRITON_CMD_REG | TAOS_TRITON_CNTRL)))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte failed in taos_resume\n"); + return (ret); + } + reg_val = i2c_smbus_read_byte(taos_datap->client); + if ( taos_datap->working == 1) { + taos_datap->working = 0; + reg_cntrl = reg_val | TAOS_TRITON_CNTL_PWRON; + if ((ret = (i2c_smbus_write_byte_data(taos_datap->client, (TAOS_TRITON_CMD_REG | TAOS_TRITON_CNTRL), reg_cntrl))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte_data failed in ioctl als_off\n"); + return (ret); + } + } + enable_irq(tmd2711_pls_irq); + return ret; +} + +//suspend iVIZM +static int taos_suspend(struct i2c_client *client, pm_message_t mesg) { + u8 reg_val = 0,reg_cntrl = 0; + int ret = -1; + disable_irq(tmd2711_pls_irq); + if ((ret = (i2c_smbus_write_byte(taos_datap->client, (TAOS_TRITON_CMD_REG | TAOS_TRITON_CNTRL)))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte failed in taos_resume\n"); + return (ret); + } + reg_val = i2c_smbus_read_byte(taos_datap->client); + if (reg_val & TAOS_TRITON_CNTL_PWRON) { + taos_datap->working = 1; + reg_cntrl = reg_val & (~TAOS_TRITON_CNTL_PWRON); + if ((ret = (i2c_smbus_write_byte_data(taos_datap->client, (TAOS_TRITON_CMD_REG | TAOS_TRITON_CNTRL), reg_cntrl))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte_data failed in taos_suspend\n"); + return (ret); + } + } + return ret; +} +#endif +// client remove +static int __devexit taos_remove(struct i2c_client *client) { + int ret = 0; + +#if 1 // zwj mv from taos_exit + unregister_chrdev_region(taos_dev_number, TAOS_MAX_NUM_DEVICES); + device_destroy(taos_class, MKDEV(MAJOR(taos_dev_number), 0)); + cdev_del(&taos_datap->cdev); + class_destroy(taos_class); + disable_irq(tmd2711_pls_irq);//iVIZM + //if (taos_wq) + // destroy_workqueue(taos_wq);//iVIZM + kfree(taos_datap); +#endif + + return (ret); +} + +// open +static int taos_open(struct inode *inode, struct file *file) { + struct taos_data *taos_datap; + int ret = 0; + + device_released = 0; + taos_datap = container_of(inode->i_cdev, struct taos_data, cdev); + if (strcmp(taos_datap->taos_name, TAOS_DEVICE_ID) != 0) { + printk(KERN_ERR "TAOS: device name incorrect during taos_open(), get %s\n", taos_datap->taos_name); + ret = -ENODEV; + } + + enable_irq(tmd2711_pls_irq);//iVIZM + return (ret); +} + +// release +static int taos_release(struct inode *inode, struct file *file) { + struct taos_data *taos_datap; + int ret = 0; + + device_released = 1; + prox_on = 0; + prox_history_hi = 0; + prox_history_lo = 0; + taos_datap = container_of(inode->i_cdev, struct taos_data, cdev); + if (strcmp(taos_datap->taos_name, TAOS_DEVICE_ID) != 0) { + printk(KERN_ERR "TAOS: device name incorrect during taos_release(), get %s\n", taos_datap->taos_name); + ret = -ENODEV; + } + disable_irq(tmd2711_pls_irq); + return (ret); +} + +static int taos_sensors_als_on(void) { + int ret = 0, i = 0; + u8 itime = 0, reg_val = 0, reg_cntrl = 0; + //int lux_val = 0, ret = 0, i = 0, tmp = 0; + +// printk("kl# %s, line=%d \n", __func__, __LINE__); + + for (i = 0; i < TAOS_FILTER_DEPTH; i++) + lux_history[i] = -ENODATA; + //taos_als_threshold_set();//iVIZM + if ((ret = (i2c_smbus_write_byte(taos_datap->client, (TAOS_TRITON_CMD_REG|TAOS_TRITON_CMD_SPL_FN|TAOS_TRITON_CMD_ALS_INTCLR)))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte failed in ioctl als_on\n"); + return (ret); + } + itime = (((taos_cfgp->als_time/50) * 18) - 1); + itime = (~itime); + if ((ret = (i2c_smbus_write_byte_data(taos_datap->client, (TAOS_TRITON_CMD_REG | TAOS_TRITON_ALS_TIME), itime))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte_data failed in ioctl als_on\n"); + return (ret); + } + if ((ret = (i2c_smbus_write_byte_data(taos_datap->client, (TAOS_TRITON_CMD_REG|TAOS_TRITON_INTERRUPT), taos_cfgp->prox_intr_filter))) < 0) {//golden + printk(KERN_ERR "TAOS: i2c_smbus_write_byte_data failed in ioctl als_on\n"); + return (ret); + } + if ((ret = (i2c_smbus_write_byte(taos_datap->client, (TAOS_TRITON_CMD_REG | TAOS_TRITON_GAIN)))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte failed in ioctl als_on\n"); + return (ret); + } + reg_val = i2c_smbus_read_byte(taos_datap->client); + reg_val = reg_val & 0xFC; + reg_val = reg_val | (taos_cfgp->gain & 0x03); + if ((ret = (i2c_smbus_write_byte_data(taos_datap->client, (TAOS_TRITON_CMD_REG | TAOS_TRITON_GAIN), reg_val))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte_data failed in ioctl als_on\n"); + return (ret); + } + //if ((ret = (i2c_smbus_write_byte(taos_datap->client, (TAOS_TRITON_CMD_REG | TAOS_TRITON_CNTRL)))) < 0) { + // printk(KERN_ERR "TAOS: i2c_smbus_write_byte failed in ioctl als_calibrate\n"); + // return (ret); + //} + //reg_val = i2c_smbus_read_byte(taos_datap->client); + //reg_cntrl = reg_val | (TAOS_TRITON_CNTL_ADC_ENBL | TAOS_TRITON_CNTL_PWRON | TAOS_TRITON_CNTL_ALS_INT_ENBL); + reg_cntrl = (TAOS_TRITON_CNTL_ADC_ENBL | TAOS_TRITON_CNTL_PWRON | TAOS_TRITON_CNTL_ALS_INT_ENBL); + if ((ret = (i2c_smbus_write_byte_data(taos_datap->client, (TAOS_TRITON_CMD_REG | TAOS_TRITON_CNTRL), reg_cntrl))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte_data failed in ioctl als_on\n"); + return (ret); + } + + mdelay(100); + + taos_als_threshold_set();//iVIZM + return ret; +} + +// ioctls +//static int taos_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { +static int taos_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { + int prox_sum = 0, prox_mean = 0, prox_max = 0; + int lux_val = 0, ret = 0, i = 0, tmp = 0; + u16 gain_trim_val = 0; + u8 reg_val = 0, reg_cntrl = 0; + int ret_check=0; + int ret_m=0; + u8 reg_val_temp=0; + + printk("k#### %s, line=%d \n", __func__, __LINE__); + + switch (cmd) { + case TAOS_IOCTL_SENSOR_CHECK: + reg_val_temp=0; + if ((ret = (i2c_smbus_write_byte(taos_datap->client, (TAOS_TRITON_CMD_REG | TAOS_TRITON_CNTRL)))) < 0) { + printk(KERN_ERR "TAOS: TAOS_IOCTL_SENSOR_CHECK failed\n"); + return (ret); + } + reg_val_temp = i2c_smbus_read_byte(taos_datap->client); + printk(KERN_ERR "TAOS: TAOS_IOCTL_SENSOR_CHECK,prox_adc_time,%d~\n",reg_val_temp); + if ((reg_val_temp & 0xFF) == 0xF) + return -ENODATA; + + break; + + case TAOS_IOCTL_SENSOR_CONFIG: + printk(KERN_ERR "TAOS: TAOS_IOCTL_SENSOR_CONFIG,test01~\n"); + ret = copy_from_user(taos_cfgp, (struct taos_cfg *)arg, sizeof(struct taos_cfg)); + if (ret) { + printk(KERN_ERR "TAOS: copy_from_user failed in ioctl config_set\n"); + return -ENODATA; + } + + break; + + case TAOS_IOCTL_SENSOR_ON: + ret=0; + reg_val=0; + ret_m=0; + + printk(KERN_ERR "TAOS: TAOS_IOCTL_SENSOR_ON, test01~\n"); + +#if 0 + /*decide the numbers of sensors*/ + ret_m=taos_sensor_mark(); + if(ret_m <0){ + printk(KERN_ERR "TAOS: TAOS_IOCTL_SENSOR_ON, error~~\n"); + return -1; + } + if(ret_m ==0){ + printk(KERN_ERR "TAOS: TAOS_IOCTL_SENSOR_ON, num >0 ~~\n"); + return 1; + } +#endif +#if 1 + /*Register init and turn off */ + for (i = 0; i < TAOS_FILTER_DEPTH; i++){ + /*Rambo ??*/ + lux_history[i] = -ENODATA; + } +#endif + +#if 0 + for (i = 0; i < sizeof(taos_triton_reg_init); i++){ + if(i !=11){ + if ((ret = (i2c_smbus_write_byte_data(taos_datap->client, (TAOS_TRITON_CMD_REG|(TAOS_TRITON_CNTRL +i)), taos_triton_reg_init[i]))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte_data failed in ioctl als_on\n"); + return (ret); + } + } + } +#endif + /*ALS interrupt clear*/ + if ((ret = (i2c_smbus_write_byte(taos_datap->client, (TAOS_TRITON_CMD_REG|TAOS_TRITON_CMD_SPL_FN|TAOS_TRITON_CMD_ALS_INTCLR)))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte failed in ioctl als_on\n"); + return (ret); + } + + printk(KERN_ERR "TAOS: TAOS_IOCTL_SENSOR_ON, test02~\n"); + /*Register setting*/ +#if 0 + if ((ret = (i2c_smbus_write_byte_data(taos_datap->client, (TAOS_TRITON_CMD_REG|0x00), 0x00))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte_data failed in ioctl prox_on\n"); + return (ret); + } +#endif + + printk(KERN_ERR "TAOS: TAOS_IOCTL_SENSOR_ON, test03,prox_int_time,%d~\n",taos_cfgp->prox_int_time); + if ((ret = (i2c_smbus_write_byte_data(taos_datap->client, (TAOS_TRITON_CMD_REG|TAOS_TRITON_ALS_TIME), taos_cfgp->prox_int_time))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte_data failed in ioctl prox_on\n"); + return (ret); + } + + printk(KERN_ERR "TAOS: TAOS_IOCTL_SENSOR_ON, test04,prox_adc_time,%d~\n",taos_cfgp->prox_adc_time); + if ((ret = (i2c_smbus_write_byte_data(taos_datap->client, (TAOS_TRITON_CMD_REG|TAOS_TRITON_PRX_TIME), taos_cfgp->prox_adc_time))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte_data failed in ioctl prox_on\n"); + return (ret); + } + + printk(KERN_ERR "TAOS: TAOS_IOCTL_SENSOR_ON, test05,prox_wait_time,%d~\n", taos_cfgp->prox_wait_time); + if ((ret = (i2c_smbus_write_byte_data(taos_datap->client, (TAOS_TRITON_CMD_REG|TAOS_TRITON_WAIT_TIME), taos_cfgp->prox_wait_time))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte_data failed in ioctl prox_on\n"); + return (ret); + } + + printk(KERN_ERR "TAOS: TAOS_IOCTL_SENSOR_ON, test05-1,prox_intr_filter,%d~\n", taos_cfgp->prox_intr_filter); + if ((ret = (i2c_smbus_write_byte_data(taos_datap->client, (TAOS_TRITON_CMD_REG|TAOS_TRITON_INTERRUPT), taos_cfgp->prox_intr_filter))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte_data failed in ioctl prox_on\n"); + return (ret); + } + + printk(KERN_ERR "TAOS: TAOS_IOCTL_SENSOR_ON, test06,prox_config,%d~\n",taos_cfgp->prox_config); + if ((ret = (i2c_smbus_write_byte_data(taos_datap->client, (TAOS_TRITON_CMD_REG|TAOS_TRITON_PRX_CFG), taos_cfgp->prox_config))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte_data failed in ioctl prox_on\n"); + return (ret); + } + + printk(KERN_ERR "TAOS: TAOS_IOCTL_SENSOR_ON, test06,prox_pulse_cnt,%d~\n",taos_cfgp->prox_pulse_cnt); + if ((ret = (i2c_smbus_write_byte_data(taos_datap->client, (TAOS_TRITON_CMD_REG|TAOS_TRITON_PRX_COUNT), taos_cfgp->prox_pulse_cnt))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte_data failed in ioctl prox_on\n"); + return (ret); + } + /*gain*/ +#if 0 + reg_val_temp=0; + if ((ret = (i2c_smbus_write_byte(taos_datap->client, (TAOS_TRITON_CMD_REG | TAOS_TRITON_GAIN)))) < 0) { + printk(KERN_ERR "TAOS: TAOS_IOCTL_SENSOR_ON failed in ioctl als_calibrate\n"); + return (ret); + } + reg_val_temp = i2c_smbus_read_byte(taos_datap->client); + printk(KERN_ERR "TAOS: TAOS_IOCTL_SENSOR_ON, test07-1,gain_init&0xC,%d~\n",reg_val_temp&0xC); + printk(KERN_ERR "TAOS: TAOS_IOCTL_SENSOR_ON, test07-2,prox_gain&0xFC,%d~\n",(taos_cfgp->prox_gain&0xFC)); + reg_val_temp=(taos_cfgp->prox_gain&0xFC)|(reg_val_temp&0xC); + printk(KERN_ERR "TAOS: TAOS_IOCTL_SENSOR_ON, test07,%d~\n",reg_val_temp); +#endif + if ((ret = (i2c_smbus_write_byte_data(taos_datap->client, (TAOS_TRITON_CMD_REG|TAOS_TRITON_GAIN), taos_cfgp->prox_gain))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte_data failed in ioctl prox_on\n"); + return (ret); + } + + /*turn on*/ +#if 0 + reg_val_temp=0; + if ((ret = (i2c_smbus_write_byte(taos_datap->client, (TAOS_TRITON_CMD_REG | TAOS_TRITON_CNTRL)))) < 0) { + printk(KERN_ERR "TAOS: TAOS_IOCTL_SENSOR_ON failed in ioctl als_calibrate\n"); + return (ret); + } + reg_val_temp = i2c_smbus_read_byte(taos_datap->client); + printk(KERN_ERR "TAOS: TAOS_IOCTL_SENSOR_ON, test08-1,%d~\n",reg_val_temp); + printk(KERN_ERR "TAOS: TAOS_IOCTL_SENSOR_ON, test08-2,%d~\n",(reg_val_temp&0x40)); + reg_val_temp=(0xF&0x3F)|(reg_val_temp&0x40); + + printk(KERN_ERR "TAOS: TAOS_IOCTL_SENSOR_ON, test08,%d~\n",reg_val_temp); +#endif + if ((ret = (i2c_smbus_write_byte_data(taos_datap->client, (TAOS_TRITON_CMD_REG|TAOS_TRITON_CNTRL), 0xF))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte_data failed in ioctl prox_on\n"); + return (ret); + } + + break; + + + case TAOS_IOCTL_SENSOR_OFF: + ret=0; + reg_val=0; + ret_check=0; + ret_m=0; + +#if 0 + /*chech the num of used sensor*/ + ret_check=taos_sensor_check(); + + printk(KERN_ERR "TAOS: TAOS_IOCTL_SENSOR_OFF,test01~\n"); + if(ret_check <0){ + printk(KERN_ERR "TAOS: TAOS_IOCTL_SENSOR_OFF, error~~\n"); + return -1; + } + if(ret_check ==0){ + printk(KERN_ERR "TAOS: TAOS_IOCTL_SENSOR_ON, num >1 ~~\n"); + return 1; + } +#endif + /*turn off*/ + printk(KERN_ERR "TAOS: TAOS_IOCTL_SENSOR_OFF,test02~\n"); + if ((ret = (i2c_smbus_write_byte_data(taos_datap->client, (TAOS_TRITON_CMD_REG|0x00), 0x00))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte_data failed in ioctl prox_off\n"); + return (ret); + } + + break; + case TAOS_IOCTL_ALS_ON: + printk("####################################\n"); + printk("######## TAOS IOCTL ALS ON #########\n"); + printk("####################################\n"); + + + printk("taos==== TAOS IOCTL ALS ON ===00==ALS_ON=%d prox_on=%d\n",ALS_ON,prox_on); + + if ((ret = (i2c_smbus_write_byte(taos_datap->client, (TAOS_TRITON_CMD_REG | TAOS_TRITON_CNTRL)))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte failed in ioctl als_calibrate\n"); + return (ret); + } + reg_val = i2c_smbus_read_byte(taos_datap->client); + + if ((reg_val & TAOS_TRITON_CNTL_PROX_DET_ENBL) == 0x0) { + printk("taos==== TAOS_IOCTL_ALS_ON ===TAOS_IOCTL_PROX_OFF\n"); + taos_sensors_als_on(); + } + + /* for (i = 0; i < TAOS_FILTER_DEPTH; i++) + lux_history[i] = -ENODATA; + //taos_als_threshold_set();//iVIZM + if ((ret = (i2c_smbus_write_byte(taos_datap->client, (TAOS_TRITON_CMD_REG|TAOS_TRITON_CMD_SPL_FN|TAOS_TRITON_CMD_ALS_INTCLR)))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte failed in ioctl als_on\n"); + return (ret); + } + itime = (((taos_cfgp->als_time/50) * 18) - 1); + itime = (~itime); + if ((ret = (i2c_smbus_write_byte_data(taos_datap->client, (TAOS_TRITON_CMD_REG | TAOS_TRITON_ALS_TIME), itime))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte_data failed in ioctl als_on\n"); + return (ret); + } + if ((ret = (i2c_smbus_write_byte_data(taos_datap->client, (TAOS_TRITON_CMD_REG|TAOS_TRITON_INTERRUPT), taos_cfgp->prox_intr_filter))) < 0) {//golden + printk(KERN_ERR "TAOS: i2c_smbus_write_byte_data failed in ioctl als_on\n"); + return (ret); + } + if ((ret = (i2c_smbus_write_byte(taos_datap->client, (TAOS_TRITON_CMD_REG | TAOS_TRITON_GAIN)))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte failed in ioctl als_on\n"); + return (ret); + } + reg_val = i2c_smbus_read_byte(taos_datap->client); + reg_val = reg_val & 0xFC; + reg_val = reg_val | (taos_cfgp->gain & 0x03); + if ((ret = (i2c_smbus_write_byte_data(taos_datap->client, (TAOS_TRITON_CMD_REG | TAOS_TRITON_GAIN), reg_val))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte_data failed in ioctl als_on\n"); + return (ret); + } + if ((ret = (i2c_smbus_write_byte(taos_datap->client, (TAOS_TRITON_CMD_REG | TAOS_TRITON_CNTRL)))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte failed in ioctl als_calibrate\n"); + return (ret); + } + reg_val = i2c_smbus_read_byte(taos_datap->client); + reg_cntrl = reg_val | (TAOS_TRITON_CNTL_ADC_ENBL | TAOS_TRITON_CNTL_PWRON | TAOS_TRITON_CNTL_ALS_INT_ENBL); + if ((ret = (i2c_smbus_write_byte_data(taos_datap->client, (TAOS_TRITON_CMD_REG | TAOS_TRITON_CNTRL), reg_cntrl))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte_data failed in ioctl als_on\n"); + return (ret); + } + taos_als_threshold_set();//iVIZM + */ + ALS_ON = 1; + printk("taos==== TAOS IOCTL ALS ON ===11==ALS_ON=%d prox_on=%d\n",ALS_ON,prox_on); + return (ret); + break; + case TAOS_IOCTL_ALS_OFF: + printk("#####################################\n"); + printk("######## TAOS IOCTL ALS OFF #########\n"); + printk("#####################################\n"); + + printk("taos==== TAOS IOCTL ALS OFF ===00==ALS_ON=%d prox_on=%d\n",ALS_ON,prox_on); + + for (i = 0; i < TAOS_FILTER_DEPTH; i++) + lux_history[i] = -ENODATA; + if ((ret = (i2c_smbus_write_byte(taos_datap->client, (TAOS_TRITON_CMD_REG | TAOS_TRITON_CNTRL)))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte failed in ioctl als_calibrate\n"); + return (ret); + } + reg_val = i2c_smbus_read_byte(taos_datap->client); + if ((reg_val & TAOS_TRITON_CNTL_PROX_DET_ENBL) == 0x0) { + + printk("taos==== TAOS_IOCTL_ALS_OFF ===TAOS_IOCTL_PROX_OFF\n"); + + if ((ret = (i2c_smbus_write_byte_data(taos_datap->client, (TAOS_TRITON_CMD_REG | TAOS_TRITON_CNTRL), 0x00))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte_data failed in ioctl als_off\n"); + return (ret); + } + cancel_work_sync(&taos_datap->work);//golden + // reg_cntrl = reg_val & (~TAOS_TRITON_CNTL_ALS_INT_ENBL); + // } else { + // reg_cntrl = reg_val & (~(TAOS_TRITON_CNTL_ADC_ENBL | TAOS_TRITON_CNTL_PWRON | TAOS_TRITON_CNTL_ALS_INT_ENBL)); + // printk("===========cancel_work_sync======als====\n"); + // cancel_work_sync(&taos_datap->work);//golden + // } + // if ((ret = (i2c_smbus_write_byte_data(taos_datap->client, (TAOS_TRITON_CMD_REG | TAOS_TRITON_CNTRL), reg_cntrl))) < 0) { + // printk(KERN_ERR "TAOS: i2c_smbus_write_byte_data failed in ioctl als_off\n"); + // return (ret); + } + ALS_ON = 0; + printk("taos==== TAOS IOCTL ALS OFF ===11==ALS_ON=%d prox_on=%d\n",ALS_ON,prox_on); + return (ret); + break; + case TAOS_IOCTL_ALS_DATA: + if ((ret = (i2c_smbus_write_byte(taos_datap->client, (TAOS_TRITON_CMD_REG | TAOS_TRITON_CNTRL)))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte failed in ioctl als_data\n"); + return (ret); + } + reg_val = i2c_smbus_read_byte(taos_datap->client); + if ((reg_val & (TAOS_TRITON_CNTL_ADC_ENBL | TAOS_TRITON_CNTL_PWRON)) != (TAOS_TRITON_CNTL_ADC_ENBL | TAOS_TRITON_CNTL_PWRON)) + return -ENODATA; + if ((ret = (i2c_smbus_write_byte(taos_datap->client, (TAOS_TRITON_CMD_REG | TAOS_TRITON_STATUS)))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte failed in ioctl als_data\n"); + return (ret); + } + reg_val = i2c_smbus_read_byte(taos_datap->client); + if ((reg_val & TAOS_TRITON_STATUS_ADCVALID) != TAOS_TRITON_STATUS_ADCVALID) + return -ENODATA; + if ((lux_val = taos_get_lux()) < 0) + printk(KERN_ERR "TAOS: call to taos_get_lux() returned error %d in ioctl als_data\n", lux_val); + //lux_val = taos_lux_filter(lux_val); + return (lux_val); + break; + case TAOS_IOCTL_ALS_CALIBRATE: + if ((ret = (i2c_smbus_write_byte(taos_datap->client, (TAOS_TRITON_CMD_REG | TAOS_TRITON_CNTRL)))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte failed in ioctl als_calibrate\n"); + return (ret); + } + reg_val = i2c_smbus_read_byte(taos_datap->client); + if ((reg_val & 0x07) != 0x07) + return -ENODATA; + if ((ret = (i2c_smbus_write_byte(taos_datap->client, (TAOS_TRITON_CMD_REG | TAOS_TRITON_STATUS)))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte failed in ioctl als_calibrate\n"); + + return (ret); + } + reg_val = i2c_smbus_read_byte(taos_datap->client); + if ((reg_val & 0x01) != 0x01) + return -ENODATA; + if ((lux_val = taos_get_lux()) < 0) { + printk(KERN_ERR "TAOS: call to lux_val() returned error %d in ioctl als_data\n", lux_val); + return (lux_val); + } + gain_trim_val = (u16)(((taos_cfgp->calibrate_target) * 512)/lux_val); + taos_cfgp->gain_trim = (int)gain_trim_val; + return ((int)gain_trim_val); + break; + case TAOS_IOCTL_CONFIG_GET: + ret = copy_to_user((struct taos_cfg *)arg, taos_cfgp, sizeof(struct taos_cfg)); + if (ret) { + printk(KERN_ERR "TAOS: copy_to_user failed in ioctl config_get\n"); + return -ENODATA; + } + return (ret); + break; + case TAOS_IOCTL_CONFIG_SET: + printk("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"); + printk("^^^^^^^^^ TAOS INCTL CONFIG SET ^^^^^^^\n"); + printk("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"); + ret = copy_from_user(taos_cfgp, (struct taos_cfg *)arg, sizeof(struct taos_cfg)); + if (ret) { + printk(KERN_ERR "TAOS: copy_from_user failed in ioctl config_set\n"); + return -ENODATA; + } + if(taos_cfgp->als_time < 50) + taos_cfgp->als_time = 50; + if(taos_cfgp->als_time > 650) + taos_cfgp->als_time = 650; + tmp = (taos_cfgp->als_time + 25)/50; + taos_cfgp->als_time = tmp*50; + sat_als = (256 - taos_cfgp->prox_int_time) << 10; + sat_prox = (256 - taos_cfgp->prox_adc_time) << 10; + break; + case TAOS_IOCTL_PROX_ON: + printk("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"); + printk("^^^^^^^^^ TAOS IOCTL PROX ON ^^^^^^^\n"); + printk("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"); + + printk("taos==== TAOS_IOCTL_PROX_ON ===00==ALS_ON=%d prox_on=%d\n",ALS_ON,prox_on); + + prox_on = 1; + + + reg_cntrl = TAOS_TRITON_CNTL_PROX_DET_ENBL | TAOS_TRITON_CNTL_PWRON | TAOS_TRITON_CNTL_PROX_INT_ENBL | + TAOS_TRITON_CNTL_ADC_ENBL | TAOS_TRITON_CNTL_WAIT_TMR_ENBL ; + + printk("taos==== TAOS_IOCTL_PROX_ON ===00==reg_cntrl=%x\n",reg_cntrl); + if ((ret = (i2c_smbus_write_byte_data(taos_datap->client, (TAOS_TRITON_CMD_REG | TAOS_TRITON_CNTRL), reg_cntrl))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte_data failed in ioctl prox_on\n"); + return (ret); + } + + if ((ret = (i2c_smbus_write_byte_data(taos_datap->client, (TAOS_TRITON_CMD_REG|0x01), taos_cfgp->prox_int_time))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte_data failed in ioctl prox_on\n"); + return (ret); + } + if ((ret = (i2c_smbus_write_byte_data(taos_datap->client, (TAOS_TRITON_CMD_REG|0x02), taos_cfgp->prox_adc_time))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte_data failed in ioctl prox_on\n"); + return (ret); + } + if ((ret = (i2c_smbus_write_byte_data(taos_datap->client, (TAOS_TRITON_CMD_REG|0x03), taos_cfgp->prox_wait_time))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte_data failed in ioctl prox_on\n"); + return (ret); + } + + if ((ret = (i2c_smbus_write_byte_data(taos_datap->client, (TAOS_TRITON_CMD_REG|0x0C), taos_cfgp->prox_intr_filter))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte_data failed in ioctl prox_on\n"); + return (ret); + } + if ((ret = (i2c_smbus_write_byte_data(taos_datap->client, (TAOS_TRITON_CMD_REG|0x0D), taos_cfgp->prox_config))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte_data failed in ioctl prox_on\n"); + return (ret); + } + if ((ret = (i2c_smbus_write_byte_data(taos_datap->client, (TAOS_TRITON_CMD_REG|0x0E), taos_cfgp->prox_pulse_cnt))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte_data failed in ioctl prox_on\n"); + return (ret); + } + if ((ret = (i2c_smbus_write_byte_data(taos_datap->client, (TAOS_TRITON_CMD_REG|0x0F), taos_cfgp->prox_gain))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte_data failed in ioctl prox_on\n"); + return (ret); + } + //if ((ret = (i2c_smbus_write_byte(taos_datap->client, (TAOS_TRITON_CMD_REG | TAOS_TRITON_CNTRL)))) < 0) { + // printk(KERN_ERR "TAOS: i2c_smbus_write_byte failed in ioctl prox_on\n"); + // return (ret); + //} + //reg_val = i2c_smbus_read_byte(taos_datap->client); + //reg_cntrl = reg_val | (TAOS_TRITON_CNTL_PROX_DET_ENBL | TAOS_TRITON_CNTL_PWRON | TAOS_TRITON_CNTL_PROX_INT_ENBL | TAOS_TRITON_CNTL_ADC_ENBL); + + mdelay(100); + + taos_prox_threshold_set();//iVIZM + + printk("taos==== TAOS_IOCTL_PROX_ON ===11==ALS_ON=%d prox_on=%d\n",ALS_ON,prox_on); + break; + case TAOS_IOCTL_PROX_OFF: + printk("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"); + printk("^^^^^^^^^ TAOS IOCTL PROX OFF ^^^^^^^\n"); + printk("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"); + + + printk("taos==== TAOS_IOCTL_PROX_OFF ===00==ALS_ON=%d prox_on=%d\n",ALS_ON,prox_on); + //if ((ret = (i2c_smbus_write_byte(taos_datap->client, (TAOS_TRITON_CMD_REG | TAOS_TRITON_CNTRL)))) < 0) { + // printk(KERN_ERR "TAOS: i2c_smbus_write_byte failed in ioctl als_calibrate\n"); + // return (ret); + //} + //reg_val = i2c_smbus_read_byte(taos_datap->client); + //if (reg_val & TAOS_TRITON_CNTL_ALS_INT_ENBL) { + // reg_cntrl = reg_val & (~(TAOS_TRITON_CNTL_PROX_DET_ENBL | TAOS_TRITON_CNTL_PROX_INT_ENBL)); + //} else { + // reg_cntrl = reg_val & (~(TAOS_TRITON_CNTL_PROX_DET_ENBL | TAOS_TRITON_CNTL_PWRON | TAOS_TRITON_CNTL_PROX_INT_ENBL)); + //reg_cntrl = reg_val & (~(TAOS_TRITON_CNTL_PROX_DET_ENBL | TAOS_TRITON_CNTL_PWRON | TAOS_TRITON_CNTL_PROX_INT_ENBL)); + // printk("===========cancel_work_sync=====prox=====\n"); + // cancel_work_sync(&taos_datap->work);//golden + //} + if ((ret = (i2c_smbus_write_byte_data(taos_datap->client, (TAOS_TRITON_CMD_REG | TAOS_TRITON_CNTRL), 0x00))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte_data failed in ioctl als_off\n"); + return (ret); + } + if (ALS_ON == 1) { + taos_sensors_als_on(); + } else { + cancel_work_sync(&taos_datap->work);//golden + } + prox_on = 0; + printk("taos==== TAOS_IOCTL_PROX_OFF ===11==ALS_ON=%d prox_on=%d\n",ALS_ON,prox_on); + break; + case TAOS_IOCTL_PROX_DATA: + //Rambo +#if 1 + if ((ret = taos_prox_poll(prox_cur_infop)) < 0) { + printk(KERN_ERR "TAOS: call to prox_poll failed in taos_prox_poll_timer_func()\n"); + return ret; + } +#endif + ret = copy_to_user((struct taos_prox_info *)arg, prox_cur_infop, sizeof(struct taos_prox_info)); + if (ret) { + printk(KERN_ERR "TAOS: copy_to_user failed in ioctl prox_data\n"); + return -ENODATA; + } + return (ret); + break; + case TAOS_IOCTL_PROX_EVENT: + if ((ret = taos_prox_poll(prox_cur_infop)) < 0) { + printk(KERN_ERR "TAOS: call to prox_poll failed in taos_prox_poll_timer_func()\n"); + return ret; + } + + return (prox_cur_infop->prox_event); + break; + case TAOS_IOCTL_PROX_CALIBRATE: + //if (prox_on) golden + //del_timer(&prox_poll_timer); + //else { + //printk(KERN_ERR "TAOS: ioctl prox_calibrate was called before ioctl prox_on was called\n"); + //return -EPERM; + //} + if ((ret = (i2c_smbus_write_byte_data(taos_datap->client, (TAOS_TRITON_CMD_REG|0x01), taos_cfgp->prox_int_time))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte_data failed in ioctl prox_on\n"); + return (ret); + } + if ((ret = (i2c_smbus_write_byte_data(taos_datap->client, (TAOS_TRITON_CMD_REG|0x02), taos_cfgp->prox_adc_time))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte_data failed in ioctl prox_on\n"); + return (ret); + } + if ((ret = (i2c_smbus_write_byte_data(taos_datap->client, (TAOS_TRITON_CMD_REG|0x03), taos_cfgp->prox_wait_time))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte_data failed in ioctl prox_on\n"); + return (ret); + } + + if ((ret = (i2c_smbus_write_byte_data(taos_datap->client, (TAOS_TRITON_CMD_REG|0x0D), taos_cfgp->prox_config))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte_data failed in ioctl prox_on\n"); + return (ret); + } + + if ((ret = (i2c_smbus_write_byte_data(taos_datap->client, (TAOS_TRITON_CMD_REG|0x0E), taos_cfgp->prox_pulse_cnt))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte_data failed in ioctl prox_on\n"); + return (ret); + } + if ((ret = (i2c_smbus_write_byte_data(taos_datap->client, (TAOS_TRITON_CMD_REG|0x0F), taos_cfgp->prox_gain))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte_data failed in ioctl prox_on\n"); + return (ret); + } + //if ((ret = (i2c_smbus_write_byte(taos_datap->client, (TAOS_TRITON_CMD_REG | TAOS_TRITON_CNTRL)))) < 0) { + // printk(KERN_ERR "TAOS: i2c_smbus_write_byte failed in ioctl prox_on\n"); + // return (ret); + //} + //reg_val = i2c_smbus_read_byte(taos_datap->client); + reg_cntrl = reg_val | (TAOS_TRITON_CNTL_PROX_DET_ENBL | TAOS_TRITON_CNTL_PWRON | TAOS_TRITON_CNTL_ADC_ENBL); + if ((ret = (i2c_smbus_write_byte_data(taos_datap->client, (TAOS_TRITON_CMD_REG | TAOS_TRITON_CNTRL), reg_cntrl))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte_data failed in ioctl prox_on\n"); + return (ret); + } + + prox_sum = 0; + prox_max = 0; + for (i = 0; i < 20; i++) { + if ((ret = taos_prox_poll(&prox_cal_info[i])) < 0) { + printk(KERN_ERR "TAOS: call to prox_poll failed in ioctl prox_calibrate\n"); + return (ret); + } + prox_sum += prox_cal_info[i].prox_data; + if (prox_cal_info[i].prox_data > prox_max) + prox_max = prox_cal_info[i].prox_data; + mdelay(100); + } + prox_mean = prox_sum/20; + taos_cfgp->prox_threshold_hi = ((((prox_max - prox_mean) * 200) + 50)/100) + prox_mean; + taos_cfgp->prox_threshold_lo = ((((prox_max - prox_mean) * 170) + 50)/100) + prox_mean; + printk("TAOS:------------ taos_cfgp->prox_threshold_hi = %d\n",taos_cfgp->prox_threshold_hi ); + printk("TAOS:------------ taos_cfgp->prox_threshold_lo = %d\n",taos_cfgp->prox_threshold_lo ); + // if (taos_cfgp->prox_threshold_lo < ((sat_prox*12)/100)) { + // taos_cfgp->prox_threshold_lo = ((sat_prox*12)/100); + // taos_cfgp->prox_threshold_hi = ((sat_prox*15)/100); + // } + for (i = 0; i < sizeof(taos_triton_reg_init); i++){ + if(i !=11){ + if ((ret = (i2c_smbus_write_byte_data(taos_datap->client, (TAOS_TRITON_CMD_REG|(TAOS_TRITON_CNTRL +i)), taos_triton_reg_init[i]))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte_data failed in ioctl als_on\n"); + return (ret); + } + } + } + + //taos_prox_poll_timer_start();//Rambo + break; + default: + return -EINVAL; + break; + } + return (ret); +} + +// read/calculate lux value +static int taos_get_lux(void) { + u16 raw_clear = 0, raw_ir = 0, raw_lux = 0; + u32 lux = 0; + u32 ratio = 0; + u8 dev_gain = 0; + u16 Tint = 0; + struct lux_data *p; + int ret = 0; + u8 chdata[4]; + int tmp = 0, i = 0; + + for (i = 0; i < 4; i++) { + if ((ret = (i2c_smbus_write_byte(taos_datap->client, (TAOS_TRITON_CMD_REG | (TAOS_TRITON_ALS_CHAN0LO + i))))) < 0) { + printk(KERN_ERR "TAOS: i2c_smbus_write_byte() to chan0/1/lo/hi reg failed in taos_get_lux()\n"); + return (ret); + } + chdata[i] = i2c_smbus_read_byte(taos_datap->client); + printk("ch(%d),data=%d\n",i,chdata[i]); + } + printk("ch0=%d\n",chdata[0]+chdata[1]*256); + printk("ch1=%d\n",chdata[2]+chdata[3]*256); + + tmp = (taos_cfgp->als_time + 25)/50; //if atime =100 tmp = (atime+25)/50=2.5 tine = 2.7*(256-atime)= 412.5 + TritonTime.numerator = 1; + TritonTime.denominator = tmp; + + tmp = 300 * taos_cfgp->als_time; //tmp = 300*atime 400 + if(tmp > 65535) + tmp = 65535; + TritonTime.saturation = tmp; + raw_clear = chdata[1]; + raw_clear <<= 8; + raw_clear |= chdata[0]; + raw_ir = chdata[3]; + raw_ir <<= 8; + raw_ir |= chdata[2]; + + raw_clear *= (taos_cfgp->scale_factor *11 ); + raw_ir *= (taos_cfgp->scale_factor *3 ); + + if(raw_ir > raw_clear) { + raw_lux = raw_ir; + raw_ir = raw_clear; + raw_clear = raw_lux; + } + dev_gain = taos_triton_gain_table[taos_cfgp->gain & 0x3]; + if(raw_clear >= lux_timep->saturation) + return(TAOS_MAX_LUX); + if(raw_ir >= lux_timep->saturation) + return(TAOS_MAX_LUX); + if(raw_clear == 0) + return(0); + if(dev_gain == 0 || dev_gain > 127) { + printk(KERN_ERR "TAOS: dev_gain = 0 or > 127 in taos_get_lux()\n"); + return -1; + } + if(lux_timep->denominator == 0) { + printk(KERN_ERR "TAOS: lux_timep->denominator = 0 in taos_get_lux()\n"); + return -1; + } + ratio = (raw_ir<<15)/raw_clear; + for (p = lux_tablep; p->ratio && p->ratio < ratio; p++); + if(!p->ratio) {//iVIZM + if(lux_history[0] < 0) + return 0; + else + return lux_history[0]; + } + Tint = taos_cfgp->als_time; + raw_clear = ((raw_clear*400 + (dev_gain>>1))/dev_gain + (Tint>>1))/Tint; + raw_ir = ((raw_ir*400 +(dev_gain>>1))/dev_gain + (Tint>>1))/Tint; + lux = ((raw_clear*(p->clear)) - (raw_ir*(p->ir))); + lux = (lux + 32768)/65536; + if(lux > TAOS_MAX_LUX) { + lux = TAOS_MAX_LUX; + } + //return(lux)*taos_cfgp->filter_count; + return(lux); +} + +/*static int taos_lux_filter(int lux) +{ + static u8 middle[] = {1,0,2,0,0,2,0,1}; + int index; + + lux_history[2] = lux_history[1]; + lux_history[1] = lux_history[0]; + lux_history[0] = lux; + + if(lux_history[2] < 0) { //iVIZM + if(lux_history[1] > 0) + return lux_history[1]; + else + return lux_history[0]; + } + index = 0; + if( lux_history[0] > lux_history[1] ) + index += 4; + if( lux_history[1] > lux_history[2] ) + index += 2; + if( lux_history[0] > lux_history[2] ) + index++; + return(lux_history[middle[index]]); +}*/ + + +// verify device +static int taos_device_name(unsigned char *bufp, char **device_name) { + if( (bufp[0x12]&0x00)!=0x00) + return(0); + //if(bufp[0x10]|bufp[0x1a]|bufp[0x1b]|bufp[0x1c]|bufp[0x1d]|bufp[0x1e]) + // return(0); + if(bufp[0x13]&0x0c) + return(0); + *device_name="tritonFN"; + return(1); +} + +// proximity poll +static int taos_prox_poll(struct taos_prox_info *prxp) { + //static int event = 0; + //u16 status = 0; + int i = 0, ret = 0; //wait_count = 0; + u8 chdata[6]; + + for (i = 0; i < 6; i++) { + chdata[i] = (i2c_smbus_read_byte_data(taos_datap->client, (TAOS_TRITON_CMD_REG | TAOS_TRITON_CMD_AUTO | (TAOS_TRITON_ALS_CHAN0LO + i)))); + } + prxp->prox_clear = chdata[1]; + prxp->prox_clear <<= 8; + prxp->prox_clear |= chdata[0]; + if (prxp->prox_clear > ((sat_als*80)/100)) + return -ENODATA; + prxp->prox_data = chdata[5]; + prxp->prox_data <<= 8; + prxp->prox_data |= chdata[4]; + + return (ret); +} + +// prox poll timer function +static void taos_prox_poll_timer_func(unsigned long param) { + int ret = 0; + + if (!device_released) { + if ((ret = taos_prox_poll(prox_cur_infop)) < 0) { + printk(KERN_ERR "TAOS: call to prox_poll failed in taos_prox_poll_timer_func()\n"); + return; + } + taos_prox_poll_timer_start(); + } + return; +} + +// start prox poll timer +static void taos_prox_poll_timer_start(void) { + init_timer(&prox_poll_timer); + prox_poll_timer.expires = jiffies + (HZ/10); + prox_poll_timer.function = taos_prox_poll_timer_func; + add_timer(&prox_poll_timer); + return; +} + +// driver init +static int __init taos_init(void) { + int ret = 0, i = 0, k = 0; + //struct i2c_adapter *my_adap; + + //tmd2711_pls_config_pins(); + //LDO_TurnOnLDO(LDO_LDO_VDD28); + //printk(KERN_ERR "TAOS:init()\n"); + + if ((ret = (i2c_add_driver(&taos_driver))) < 0) { + printk(KERN_ERR "TAOS: i2c_add_driver() failed in taos_init()\n"); + return (ret); + } + //printk(KERN_ERR "TAOS:end(ret [%d])\n ",ret); + return (ret); +} + +// driver exit +static void __exit taos_exit(void) { + i2c_del_driver(&taos_driver); +} + +MODULE_AUTHOR("John Koshi - Surya Software"); +MODULE_DESCRIPTION("TAOS ambient light and proximity sensor driver"); +MODULE_LICENSE("GPL"); + +module_init(taos_init); +module_exit(taos_exit); + |
