static void proxsensor_get_avgvalue(struct gp2a_data *data) { int min = 0, max = 0, avg = 0; int i; u8 proximity_value = 0; unsigned char get_D2_data[2] = { 0, }; for (i = 0; i < PROX_READ_NUM; i++) { msleep(20); opt_i2c_read(0x10, get_D2_data, sizeof(get_D2_data)); proximity_value = (get_D2_data[1] << 8) | get_D2_data[0]; avg += proximity_value; if (!i) min = proximity_value; else if (proximity_value < min) min = proximity_value; if (proximity_value > max) max = proximity_value; } avg /= PROX_READ_NUM; data->average[0] = min; data->average[1] = avg; data->average[2] = max; }
static u8 proximity_adc_read(struct gp2a_data *gp2a) { int adc_arr[OFFSET_ARRAY_LENGTH]; int total = 0, min = 0, max = 0; u8 avg = 0; int D2_data = 0; unsigned char get_D2_data[2] = {0,}; int i; for (i = 0; i < OFFSET_ARRAY_LENGTH; i++) { mdelay(50); mutex_lock(&gp2a->data_mutex); opt_i2c_read(0x10, get_D2_data, sizeof(get_D2_data)); mutex_unlock(&gp2a->data_mutex); D2_data = (get_D2_data[1] << 8) | get_D2_data[0]; adc_arr[i] = D2_data; if (i == 0) { min = adc_arr[i]; max = adc_arr[i]; } else { if (adc_arr[i] < min) min = adc_arr[i]; else if (adc_arr[i] > max) max = adc_arr[i]; } total += adc_arr[i]; } total -= (min + max); avg = (u8)(total / (OFFSET_ARRAY_LENGTH - 2)); pr_info("%s: offset = %d\n", __func__, avg); return avg; }
static ssize_t proximity_raw_data_show(struct device *dev, struct device_attribute *attr, char *buf) { int D2_data = 0; unsigned char get_D2_data[2] = { 0, }; msleep(20); opt_i2c_read(0x10, get_D2_data, sizeof(get_D2_data)); D2_data = (get_D2_data[1] << 8) | get_D2_data[0]; return sprintf(buf, "%d\n", D2_data); }
static ssize_t proximity_raw_data_show(struct device *dev, struct device_attribute *attr, char *buf) { int D2_data = 0; unsigned char get_D2_data[2] = { 0, }; struct gp2a_data *data = dev_get_drvdata(dev); mutex_lock(&data->data_mutex); opt_i2c_read(0x10, get_D2_data, sizeof(get_D2_data)); mutex_unlock(&data->data_mutex); D2_data = (get_D2_data[1] << 8) | get_D2_data[0]; return sprintf(buf, "%d\n", D2_data); }
static char get_ps_vout_value(void) { char value = 0; #ifdef PROX_MODE_A value = gpio_get_value_cansleep(GPIO_PS_VOUT); #else //PROX_MODE_A opt_i2c_read(0x00, &value, 2); value &= 0x01; value ^= 0x01; #endif //PROX_MODE_A return value; }
static ssize_t proximity_cal_show(struct device *dev, struct device_attribute *attr, char *buf) { struct gp2a_data *gp2a = dev_get_drvdata(dev); int thresh_hi = 0; unsigned char get_D2_data[2]={0,}; msleep(20); opt_i2c_read(PS_HT_LSB, get_D2_data, sizeof(get_D2_data)); thresh_hi =(get_D2_data[1] << 8) | get_D2_data[0]; gp2a->threshold_high = thresh_hi; printk(KERN_INFO "[GP2A] %s : %d, %d\n",__func__, gp2a->offset_value, gp2a->threshold_high); return sprintf(buf, "%d,%d\n", gp2a->offset_value, gp2a->threshold_high); }
static char get_ps_vout_value(void) { char value = 0; #ifdef PROX_MODE_A #if 1 //defined (CONFIG_MACH_STEALTH) value = gpio_get_value_cansleep(GPIO_PS_VOUT); #else value = gpio_get_value(GPIO_PS_VOUT); #endif #else //PROX_MODE_A opt_i2c_read(0x00, &value, 2); value &= 0x01; value ^= 0x01; #endif //PROX_MODE_A return value; }
irqreturn_t gp2a_irq_handler(int irq, void *ptr) { struct gp2a_data *gp2a = ptr; char value; #ifdef PROX_MODE_B u8 reg = 0; #endif #ifdef PROX_MODE_A value = gpio_get_value_cansleep(gp2a->ps_status); #else opt_i2c_read(0x00, &value, 2); value &= 0x01; value ^= 0x01; #endif input_report_abs(gp2a->input_dev, ABS_DISTANCE, value); input_sync(gp2a->input_dev); gp2a->prox_data = value; #ifdef PROX_MODE_B if (value == 1) { reg = 0x40; opt_i2c_write(NOT_INT_CLR(REGS_HYS), ®); } else{ reg = 0x27; opt_i2c_write(NOT_INT_CLR(REGS_HYS), ®); } reg = 0x18; opt_i2c_write(NOT_INT_CLR(REGS_CON), ®); #endif #ifdef PROX_MODE_B reg = 0x00; opt_i2c_write(INT_CLR(REGS_CON), ®); #endif return IRQ_HANDLED; }
static ssize_t lightsensor_raw_show(struct device *dev, struct device_attribute *attr, char *buf) { struct gp2a_data *data = dev_get_drvdata(dev); unsigned char get_data[4] = { 0, }; int D0_raw_data; int D1_raw_data; int ret = 0; mutex_lock(&data->data_mutex); ret = opt_i2c_read(DATA0_LSB, get_data, sizeof(get_data)); mutex_unlock(&data->data_mutex); if (ret < 0) pr_err("%s i2c err: %d\n", __func__, ret) ; D0_raw_data = (get_data[1] << 8) | get_data[0]; /* clear */ D1_raw_data = (get_data[3] << 8) | get_data[2]; /* IR */ return snprintf(buf, PAGE_SIZE, "%d,%d\n", D0_raw_data, D1_raw_data); }
static ssize_t proximity_state_show(struct device *dev, struct device_attribute *attr, char *buf) { struct gp2a_data *data = dev_get_drvdata(dev); static int count; /*count for proximity average */ int D2_data = 0; unsigned char get_D2_data[2] = { 0, }; mutex_lock(&data->data_mutex); opt_i2c_read(0x10, get_D2_data, sizeof(get_D2_data), data->pdata->addr, data->pdata->adapt_num); mutex_unlock(&data->data_mutex); D2_data = (get_D2_data[1] << 8) | get_D2_data[0]; data->average[count] = D2_data; count++; if (count == PROX_READ_NUM) count = 0; return snprintf(buf, PAGE_SIZE, "%d\n", D2_data); }
static int proximity_adc_read(struct gp2a_data *gp2a) { int sum[OFFSET_ARRAY_LENGTH]; int i = 0; int avg = 0; int min = 0; int max = 0; int total = 0; int D2_data = 0; unsigned char get_D2_data[2]={0,};//test mutex_lock(&gp2a->data_mutex); for (i = 0; i < OFFSET_ARRAY_LENGTH; i++) { mdelay(50); opt_i2c_read(0x10, get_D2_data, sizeof(get_D2_data)); D2_data =(get_D2_data[1] << 8) | get_D2_data[0]; sum[i] = D2_data; if (i == 0) { min = sum[i]; max = sum[i]; } else { if (sum[i] < min) min = sum[i]; else if (sum[i] > max) max = sum[i]; } total += sum[i]; } mutex_unlock(&gp2a->data_mutex); total -= (min + max); avg = (int)(total / (OFFSET_ARRAY_LENGTH - 2)); printk(KERN_INFO "[GP2A] %s: avg = %d\n", __func__, avg); return avg; }
static void gp2a_work_func_prox(struct work_struct *work) { struct gp2a_data *gp2a = container_of(work, struct gp2a_data, work_prox); unsigned char value; unsigned char int_val=REGS_PROX; unsigned char vout=0; /* Read VO & INT Clear */ gprintk("[PROXIMITY] %s : \n",__func__); if(INT_CLEAR) { //int_val = REGS_PROX | (1 <<7); } opt_i2c_read((u8)(int_val),&value,1); vout = value & 0x01; printk(KERN_INFO "[PROXIMITY] value = %d \n",vout); /* Report proximity information */ proximity_value = vout; if(proximity_value ==0) { timeB = ktime_get(); timeSub = ktime_sub(timeB,timeA); printk(KERN_INFO "[PROXIMITY] timeSub sec = %d, timeSub nsec = %d \n",timeSub.tv.sec,timeSub.tv.nsec); if (timeSub.tv.sec>=3 ) { wake_lock_timeout(&prx_wake_lock,HZ/2); printk(KERN_INFO "[PROXIMITY] wake_lock_timeout : HZ/2 \n"); } else printk(KERN_INFO "[PROXIMITY] wake_lock is already set \n"); } if(USE_INPUT_DEVICE) { input_report_abs(gp2a->input_dev,ABS_DISTANCE,(int)vout); input_sync(gp2a->input_dev); mdelay(1); } /* Write HYS Register */ #if (SENSOR_MODE == SENSOR_MODE_B1) if(!vout) { value = 0x40; } else { value = 0x20; } #elif (SENSOR_MODE == SENSOR_MODE_B15) if(!vout) { value = 0x2F; } else { value = 0x0F; } #elif (SENSOR_MODE == SENSOR_MODE_B2) if(!vout) { value = 0x20; } else { value = 0x00; } #endif opt_i2c_write((u8)(REGS_HYS),&value); /* Forcing vout terminal to go high */ value = 0x18; opt_i2c_write((u8)(REGS_CON),&value); /* enabling VOUT terminal in nomal operation */ value = 0x00; opt_i2c_write((u8)(REGS_CON),&value); /* enable INT */ enable_irq(gp2a->irq); }
static void gp2a_work_func_prox(struct work_struct *work) { struct gp2a_data *gp2a = container_of(work, struct gp2a_data, work_prox); unsigned char value; unsigned char int_val=REGS_PROX; unsigned char vout=0; #if defined(CONFIG_MACH_RANT3) int err; static int retry = 0; #endif /* Read VO & INT Clear */ printk("[PROXIMITY] %s \n",__func__); if(INT_CLEAR) { // int_val = REGS_PROX | (1 <<7); } #if defined(CONFIG_MACH_RANT3) err = opt_i2c_read((u8)(int_val),&value,1); if(err < 0 && retry == 0) { printk("[PROXIMITY] I2C read error, try again==============================!!! \n"); retry++; schedule_delayed_work(&gp2a->work_prox, 10); return; } else retry = 0; #else opt_i2c_read((u8)(int_val),&value,1); #endif vout = value & 0x01; printk(KERN_INFO "[PROXIMITY] value = %d \n",vout); /* Report proximity information */ proximity_value = vout; if(proximity_value ==0) { /* timeB = ktime_get(); timeSub = ktime_sub(timeB,timeA); printk(KERN_INFO "[PROXIMITY] timeB = %d sec, timeA = %d sec \n",timeB.tv.sec,timeA.tv.sec); printk(KERN_INFO "[PROXIMITY] timeSub sec = %d, timeSub nsec = %d \n",timeSub.tv.sec,timeSub.tv.nsec); if (timeSub.tv.sec>=3 ) { wake_lock_timeout(&prx_wake_lock,3*HZ); printk(KERN_INFO "[PROXIMITY] wake_lock_timeout : 3sec \n"); } else printk(KERN_INFO "[PROXIMITY] wake_lock is already set \n"); */ } if(USE_INPUT_DEVICE) { input_report_abs(gp2a->input_dev,ABS_DISTANCE,(int)vout); input_sync(gp2a->input_dev); mdelay(1); } /* Write HYS Register */ if(!vout) { #if defined(CONFIG_MACH_RANT3) value = 0x2F; #else value = 0x40; #endif } else { #if defined(CONFIG_MACH_RANT3) value = 0x0F; #else value = 0x20; #endif } opt_i2c_write((u8)(REGS_HYS),&value); /* Forcing vout terminal to go high */ value = 0x18; opt_i2c_write((u8)(REGS_CON),&value); /* enable INT */ enable_irq(gp2a->irq); /* enabling VOUT terminal in nomal operation */ value = 0x00; opt_i2c_write((u8)(REGS_CON),&value); printk("[PROXIMITY] end %s \n",__func__); }
/***************************************************************************************** * * function : gp2a_work_func_prox * description : This function is for proximity sensor (using B-1 Mode ). * when INT signal is occured , it gets value from VO register. */ void gp2a_work_func_prox(struct work_struct *work) { struct gp2a_data *gp2a = container_of(work, struct gp2a_data, work_prox); unsigned char value; unsigned char vout = 0; if (proximity_enable == OFF) { gprintk("proximity is not enable\n"); return; } //20111001 [email protected] : change disable step for Mode B1 disable_irq_nosync(gp2a->irq); //20111001 [email protected] : Set Operation mode B1 for X2 New HW Revision [S] /* Procedure 5 - Read VO & INT Clear */ value = opt_i2c_read(gp2a, REGS_PROX); //Report Data toward HAL [S] vout = (value & 0x01)?0:1; //20110706 [email protected] : for diag test mode. 250.49 [S] if(vout) proximity_status = 0; else proximity_status = 1; //20110706 [email protected] : for diag test mode. 250.49 [E] gprintk("value = %x, vout = %d\n",value, vout); wake_lock_timeout(&gp2a_wake_lock, 3 * HZ); input_report_abs(gp2a->input_dev,ABS_DISTANCE,(int)vout); input_sync(gp2a->input_dev); mdelay(1); //Reposrt Data toward HAL [E] /* Procedure 6 - Write HYS Register */ //20111110 - [email protected] - Revision 처리 추가! - HW Tuning for Touch Window[S] #if defined(CONFIG_KS1103) if(get_lge_pcb_revision() > REV_C) { if(vout) value = 0x00; else value = 0xC3; } else { if(vout) value = 0x40; else value = 0x23; } #else if(vout) value = 0x40; else value = 0x23; #endif //20111110 - [email protected] - Revision 처리 추가! - HW Tuning for Touch Window[E] opt_i2c_write(gp2a, (u8)(REGS_HYS), value); /* Procedure 7 - Forcing vout terminal to go high */ opt_i2c_write(gp2a, (u8)(REGS_CON), 0x18); /* Procedure 8 - enable INT */ enable_irq(gp2a->irq); mdelay(2); /* Procedure 9 - enabling VOUT terminal in nomal operation */ opt_i2c_write(gp2a, (u8)(REGS_CON), 0x00); //20111001 [email protected] : Set Operation mode B1 for X2 New HW Revision [E] }
int lightsensor_get_adc(struct sensor_data *data) { unsigned char get_data[4] = { 0, }; int D0_raw_data; int D1_raw_data; int D0_data; int D1_data; int lx = 0; u8 value; int light_alpha; int light_beta; static int lx_prev; int ret = 0; #if defined(CONFIG_MACH_BAFFIN_KOR_SKT) || \ defined(CONFIG_MACH_BAFFIN_KOR_KT) || \ defined(CONFIG_MACH_BAFFIN_KOR_LGT) int d0_boundary = 91; #elif defined(CONFIG_MACH_KONA) int d0_boundary = 93; #else int d0_boundary = 93; #endif mutex_lock(&data->light_mutex); ret = opt_i2c_read(DATA0_LSB, get_data, sizeof(get_data)); mutex_unlock(&data->light_mutex); if (ret < 0) return lx_prev; D0_raw_data = (get_data[1] << 8) | get_data[0]; /* clear */ D1_raw_data = (get_data[3] << 8) | get_data[2]; /* IR */ if (is_gp2a030a()) { #if defined(CONFIG_MACH_GRANDE) if (100 * D1_raw_data <= 41 * D0_raw_data) { light_alpha = 1186; light_beta = 0; } else if (100 * D1_raw_data <= 62 * D0_raw_data) { light_alpha = 2930; light_beta = 4252; } else if (100 * D1_raw_data <= d0_boundary * D0_raw_data) { light_alpha = 924; light_beta = 1015; } else { light_alpha = 0; light_beta = 0; } #elif defined(CONFIG_MACH_BAFFIN_KOR_SKT) || \ defined(CONFIG_MACH_BAFFIN_KOR_KT) || \ defined(CONFIG_MACH_BAFFIN_KOR_LGT) if (100 * D1_raw_data <= 41 * D0_raw_data) { light_alpha = 868; light_beta = 0; } else if (100 * D1_raw_data <= 62 * D0_raw_data) { light_alpha = 2308; light_beta = 3509; } else if (100 * D1_raw_data <= d0_boundary * D0_raw_data) { light_alpha = 404; light_beta = 440; } else { light_alpha = 0; light_beta = 0; } #elif defined(CONFIG_MACH_KONA) if (100 * D1_raw_data <= 40 * D0_raw_data) { light_alpha = 834; light_beta = 0; } else if (100 * D1_raw_data <= 62 * D0_raw_data) { light_alpha = 2050; light_beta = 3036; } else if (100 * D1_raw_data <= d0_boundary * D0_raw_data) { if (D0_raw_data < 3000 && lightsensor_mode == 0) { /* Incandescent Low lux */ light_alpha = 242; light_beta = 257; } else { /* Incandescent High lux */ light_alpha = 497; light_beta = 534; } } else { light_alpha = 0; light_beta = 0; } #else if (100 * D1_raw_data <= 41 * D0_raw_data) { light_alpha = 736; light_beta = 0; } else if (100 * D1_raw_data <= 62 * D0_raw_data) { light_alpha = 1855; light_beta = 2693; } else if (100 * D1_raw_data <= d0_boundary * D0_raw_data) { light_alpha = 544; light_beta = 595; } else { light_alpha = 0; light_beta = 0; } #endif } else { if (lightsensor_mode) { /* HIGH_MODE */ if (100 * D1_raw_data <= 32 * D0_raw_data) { light_alpha = 800; light_beta = 0; } else if (100 * D1_raw_data <= 67 * D0_raw_data) { light_alpha = 2015; light_beta = 2925; } else if (100 * D1_raw_data <= d0_boundary * D0_raw_data) { light_alpha = 56; light_beta = 12; } else { light_alpha = 0; light_beta = 0; } } else { /* LOW_MODE */ if (100 * D1_raw_data <= 32 * D0_raw_data) { light_alpha = 800; light_beta = 0; } else if (100 * D1_raw_data <= 67 * D0_raw_data) { light_alpha = 2015; light_beta = 2925; } else if (100 * D1_raw_data <= d0_boundary * D0_raw_data) { light_alpha = 547; light_beta = 599; } else { light_alpha = 0; light_beta = 0; } } } if (lightsensor_mode) { /* HIGH_MODE */ D0_data = D0_raw_data * 16; D1_data = D1_raw_data * 16; } else { /* LOW_MODE */ D0_data = D0_raw_data; D1_data = D1_raw_data; } if (is_gp2a030a()) { if (D0_data < 3) { lx = 0; #ifdef DEBUG gprintk("lx is 0 : D0=%d, D1=%d\n", D0_raw_data, D1_raw_data); #endif } else if (lightsensor_mode == 0 && (D0_raw_data >= 16000 || D1_raw_data >= 16000) && (D0_raw_data <= 16383 && D1_raw_data <= 16383)) { #ifdef DEBUG gprintk("need to changed HIGH_MODE D0=%d, D1=%d\n", D0_raw_data, D1_raw_data); #endif lx = lx_prev; } else if (100 * D1_data > d0_boundary * D0_data) { lx = lx_prev; #ifdef DEBUG gprintk ("Data range over so ues prev_lx value=%d D0=%d, D1=%d mode=%d\n", lx, D0_data, D1_data, lightsensor_mode); #endif return lx; } else { lx = (int)((light_alpha / 10 * D0_data * 33) - (light_beta / 10 * D1_data * 33)) / 1000; #ifdef DEBUG gprintk ("D0=%d, D1=%d, lx=%d mode=%d a=%d, b=%d prev_lx=%d\n", D0_raw_data, D1_raw_data, lx, lightsensor_mode, light_alpha, light_beta, lx_prev); #endif } } else { if ((D0_data == 0 || D1_data == 0) && (D0_data < 300 && D1_data < 300)) { lx = 0; #ifdef DEBUG gprintk("lx is 0 : D0=%d, D1=%d\n", D0_raw_data, D1_raw_data); #endif } else if ((lightsensor_mode == 0) && (D0_raw_data >= 16000 || D1_raw_data >= 16000) && (D0_raw_data <= 16383 && D1_raw_data <= 16383)) { #ifdef DEBUG gprintk("need to changed HIGH_MODE D0=%d, D1=%d\n", D0_raw_data, D1_raw_data); #endif lx = lx_prev; } else if ((100 * D1_data > d0_boundary * D0_data) || (100 * D1_data < 15 * D0_data)) { lx = lx_prev; #ifdef DEBUG gprintk ("Data range over so ues prev_lx value=%d D0=%d, D1=%d mode=%d\n", lx, D0_data, D1_data, lightsensor_mode); #endif return lx; } else { lx = (int)((light_alpha / 10 * D0_data * 33) - (light_beta / 10 * D1_data * 33)) / 1000; #ifdef DEBUG gprintk ("D0=%d, D1=%d, lx=%d mode=%d a=%d, b=%d prev_lx=%d\n", D0_raw_data, D1_raw_data, lx, lightsensor_mode, light_alpha, light_beta, lx_prev); #endif } } lx_prev = lx; if (lightsensor_mode) { /* HIGH MODE */ if (D0_raw_data < 1000) { #ifdef DEBUG gprintk("change to LOW_MODE detection=%d\n", proximity_sensor_detection); #endif lightsensor_mode = 0; /* change to LOW MODE */ value = 0x0C; opt_i2c_write(COMMAND1, &value); if (proximity_sensor_detection) value = 0x23; else value = 0x63; opt_i2c_write(COMMAND2, &value); if (proximity_enable) value = 0xCC; else value = 0xDC; opt_i2c_write(COMMAND1, &value); } } else { /* LOW MODE */ if (D0_raw_data > 16000 || D1_raw_data > 16000) { #ifdef DEBUG gprintk("change to HIGH_MODE detection=%d\n", proximity_sensor_detection); #endif lightsensor_mode = 1; /* change to HIGH MODE */ value = 0x0C; opt_i2c_write(COMMAND1, &value); if (proximity_sensor_detection) value = 0x27; else value = 0x67; opt_i2c_write(COMMAND2, &value); if (proximity_enable) value = 0xCC; else value = 0xDC; opt_i2c_write(COMMAND1, &value); } } return lx; }
static int lightsensor_probe(struct platform_device *pdev) { struct sensor_data *data = NULL; int rt = -ENXIO; unsigned char get_data = 0; pr_info("%s, is called\n", __func__); /* Check I2C communication */ rt = opt_i2c_read(DATA0_LSB, &get_data, sizeof(get_data)); if (rt < 0) { pr_err("%s failed : threre is no such device.\n", __func__); return rt; } gprintk("probe start!\n"); data = kzalloc(sizeof(struct sensor_data), GFP_KERNEL); if (!data) { pr_err("%s: failed to alloc memory for module data\n", __func__); return -ENOMEM; } data->enabled = 0; data->delay = SENSOR_DEFAULT_DELAY; data->input_dev = input_allocate_device(); if (!data->input_dev) { pr_err("%s: could not allocate input device\n", __func__); rt = -ENOMEM; goto err_input_allocate_device_light; } input_set_capability(data->input_dev, EV_REL, REL_MISC); data->input_dev->name = SENSOR_NAME; rt = input_register_device(data->input_dev); if (rt) { pr_err("%s: could not register input device\n", __func__); input_free_device(data->input_dev); goto err_input_register_device_light; } input_set_drvdata(data->input_dev, data); rt = sysfs_create_group(&data->input_dev->dev.kobj, &lightsensor_attribute_group); if (rt) { pr_err("%s: could not create sysfs group\n", __func__); goto err_sysfs_create_group_light; } mutex_init(&data->mutex); mutex_init(&data->light_mutex); data->light_dev = sensors_classdev_register("light_sensor"); if (IS_ERR(data->light_dev)) { pr_err("%s: could not create light_dev\n", __func__); goto err_light_device_create; } if (device_create_file(data->light_dev, &dev_attr_lux) < 0) { pr_err("%s: could not create device file(%s)!\n", __func__, dev_attr_lux.attr.name); goto err_light_device_create_file; } if (device_create_file(data->light_dev, &dev_attr_vendor) < 0) { pr_err("%s: could not create device file(%s)!\n", __func__, dev_attr_vendor.attr.name); goto err_light_device_create_file1; } if (device_create_file(data->light_dev, &dev_attr_name) < 0) { pr_err("%s: could not create device file(%s)!\n", __func__, dev_attr_name.attr.name); goto err_light_device_create_file2; } if (device_create_file(data->light_dev, &dev_attr_raw_data) < 0) { pr_err("%s: could not create device file(%s)!\n", __func__, dev_attr_raw_data.attr.name); goto err_light_device_create_file3; } dev_set_drvdata(data->light_dev, data); data->wq = create_singlethread_workqueue("gp2a_wq"); if (!data->wq) { rt = -ENOMEM; pr_err("%s: could not create workqueue\n", __func__); goto err_create_workqueue; } /* this is the thread function we run on the work queue */ INIT_DELAYED_WORK(&data->work, gp2a_work_func_light); /* set platdata */ platform_set_drvdata(pdev, data); gprintk("probe success!\n"); goto done; /* error, unwind it all */ err_light_device_create_file3: device_remove_file(data->light_dev, &dev_attr_raw_data); err_light_device_create_file2: device_remove_file(data->light_dev, &dev_attr_name); err_light_device_create_file1: device_remove_file(data->light_dev, &dev_attr_vendor); err_create_workqueue: device_remove_file(data->light_dev, &dev_attr_lux); err_light_device_create_file: sensors_classdev_unregister(data->light_dev); err_light_device_create: mutex_destroy(&data->mutex); sysfs_remove_group(&data->input_dev->dev.kobj, &lightsensor_attribute_group); err_sysfs_create_group_light: input_unregister_device(data->input_dev); err_input_register_device_light: err_input_allocate_device_light: kfree(data); done: return rt; }
int lightsensor_get_adc(struct gp2a_data *data) { unsigned char get_data[4] = { 0, }; int D0_raw_data; int D1_raw_data; int D0_data; int D1_data; int lx = 0; u8 value; int light_alpha; int light_beta; static int lx_prev; int ret = 0; int d0_boundary = 91; mutex_lock(&data->data_mutex); ret = opt_i2c_read(DATA0_LSB, get_data, sizeof(get_data)); mutex_unlock(&data->data_mutex); if (ret < 0) return lx_prev; D0_raw_data = (get_data[1] << 8) | get_data[0]; /* clear */ D1_raw_data = (get_data[3] << 8) | get_data[2]; /* IR */ // Result of baffin tunning if (100 * D1_raw_data <= 41 * D0_raw_data) { light_alpha = 830; light_beta = 0; } else if (100 * D1_raw_data <= 62 * D0_raw_data) { light_alpha = 2039; light_beta = 2949; } else if (100 * D1_raw_data <= d0_boundary * D0_raw_data) { light_alpha = 649; light_beta = 708; } else { light_alpha = 0; light_beta = 0; } if (data->lightsensor_mode) { /* HIGH_MODE */ D0_data = D0_raw_data * 16; D1_data = D1_raw_data * 16; } else { /* LOW_MODE */ D0_data = D0_raw_data; D1_data = D1_raw_data; } if (D0_data < 3) { lx = 0; } else if (data->lightsensor_mode == 0 && (D0_raw_data >= 16000 || D1_raw_data >= 16000) && (D0_raw_data <= 16383 && D1_raw_data <= 16383)) { lx = lx_prev; } else if (100 * D1_data > d0_boundary * D0_data) { lx = lx_prev; return lx; } else { lx = (int)((light_alpha / 10 * D0_data * 33) - (light_beta / 10 * D1_data * 33)) / 1000; } lx_prev = lx; if (data->lightsensor_mode) { /* HIGH MODE */ if (D0_raw_data < 1000) { pr_info("%s: change to LOW_MODE detection=%d\n", __func__, data->proximity_detection); data->lightsensor_mode = 0; /* change to LOW MODE */ value = 0x0C; opt_i2c_write(COMMAND1, &value); if (data->proximity_detection) value = 0x23; else value = 0x63; opt_i2c_write(COMMAND2, &value); if (data->proximity_enabled) value = 0xCC; else value = 0xDC; opt_i2c_write(COMMAND1, &value); } } else { /* LOW MODE */ if (D0_raw_data > 16000 || D1_raw_data > 16000) { pr_info("%s: change to HIGH_MODE detection=%d\n", __func__, data->proximity_detection); /* change to HIGH MODE */ data->lightsensor_mode = 1; value = 0x0C; opt_i2c_write(COMMAND1, &value); if (data->proximity_detection) value = 0x27; else value = 0x67; opt_i2c_write(COMMAND2, &value); if (data->proximity_enabled) value = 0xCC; else value = 0xDC; opt_i2c_write(COMMAND1, &value); } } return lx; }
int lightsensor_get_adc(struct gp2a_data *data) { unsigned char get_data[4] = { 0, }; int D0_raw_data; int D1_raw_data; int D0_data; int D1_data; int lx = 0; u8 value; int light_alpha; int light_beta; static int lx_prev; int ret = 0; int d0_boundary = 92; mutex_lock(&data->data_mutex); ret = opt_i2c_read(DATA0_LSB, get_data, sizeof(get_data), data->pdata->addr, data->pdata->adapt_num); mutex_unlock(&data->data_mutex); if (ret < 0) return lx_prev; D0_raw_data = (get_data[1] << 8) | get_data[0]; /* clear */ D1_raw_data = (get_data[3] << 8) | get_data[2]; /* IR */ if (data->pdata->version) { /* GP2AP 030 */ if (100 * D1_raw_data <= 40 * D0_raw_data) { light_alpha = 935; light_beta = 0; } else if (100 * D1_raw_data <= 54 * D0_raw_data) { light_alpha = 3039; light_beta = 5176; } else if (100 * D1_raw_data <= d0_boundary * D0_raw_data) { light_alpha = 494; light_beta = 533; } else { light_alpha = 0; light_beta = 0; } } else { /* GP2AP 020 */ if (data->lightsensor_mode) { /* HIGH_MODE */ if (100 * D1_raw_data <= 32 * D0_raw_data) { light_alpha = 800; light_beta = 0; } else if (100 * D1_raw_data <= 67 * D0_raw_data) { light_alpha = 2015; light_beta = 2925; } else if (100 * D1_raw_data <= d0_boundary * D0_raw_data) { light_alpha = 56; light_beta = 12; } else { light_alpha = 0; light_beta = 0; } } else { /* LOW_MODE */ if (100 * D1_raw_data <= 32 * D0_raw_data) { light_alpha = 800; light_beta = 0; } else if (100 * D1_raw_data <= 67 * D0_raw_data) { light_alpha = 2015; light_beta = 2925; } else if (100 * D1_raw_data <= d0_boundary * D0_raw_data) { light_alpha = 547; light_beta = 599; } else { light_alpha = 0; light_beta = 0; } } } if (data->lightsensor_mode) { /* HIGH_MODE */ D0_data = D0_raw_data * 16; D1_data = D1_raw_data * 16; } else { /* LOW_MODE */ D0_data = D0_raw_data; D1_data = D1_raw_data; } if (data->pdata->version) { /* GP2AP 030 */ if (D0_data < 3) { lx = 0; } else if (data->lightsensor_mode == 0 && (D0_raw_data >= 16000 || D1_raw_data >= 16000) && (D0_raw_data <= 16383 && D1_raw_data <= 16383)) { lx = lx_prev; } else if (100 * D1_data > d0_boundary * D0_data) { lx = lx_prev; return lx; } else { lx = (int)((light_alpha / 10 * D0_data * 33) - (light_beta / 10 * D1_data * 33)) / 1000; } } else { /* GP2AP 020 */ if ((D0_data == 0 || D1_data == 0)\ && (D0_data < 300 && D1_data < 300)) { lx = 0; } else if (data->lightsensor_mode == 0 && (D0_raw_data >= 16000 || D1_raw_data >= 16000) && (D0_raw_data <= 16383 && D1_raw_data <= 16383)) { lx = lx_prev; } else if ((100 * D1_data > d0_boundary * D0_data) || (100 * D1_data < 15 * D0_data)) { lx = lx_prev; return lx; } else { lx = (int)((light_alpha / 10 * D0_data * 33) - (light_beta / 10 * D1_data * 33)) / 1000; } } lx_prev = lx; if (data->lightsensor_mode) { /* HIGH MODE */ if (D0_raw_data < 1000) { pr_info("%s: change to LOW_MODE detection=%d\n", __func__, data->proximity_detection); data->lightsensor_mode = 0; /* change to LOW MODE */ value = 0x0C; opt_i2c_write(COMMAND1, &value, data->pdata->addr, data->pdata->adapt_num); if (data->proximity_detection) value = 0x23; else value = 0x63; opt_i2c_write(COMMAND2, &value, data->pdata->addr, data->pdata->adapt_num); if (data->proximity_enabled) value = 0xCC; else value = 0xDC; opt_i2c_write(COMMAND1, &value, data->pdata->addr, data->pdata->adapt_num); } } else { /* LOW MODE */ if (D0_raw_data > 16000 || D1_raw_data > 16000) { pr_info("%s: change to HIGH_MODE detection=%d\n", __func__, data->proximity_detection); /* change to HIGH MODE */ data->lightsensor_mode = 1; value = 0x0C; opt_i2c_write(COMMAND1, &value, data->pdata->addr, data->pdata->adapt_num); if (data->proximity_detection) value = 0x27; else value = 0x67; opt_i2c_write(COMMAND2, &value, data->pdata->addr, data->pdata->adapt_num); if (data->proximity_enabled) value = 0xCC; else value = 0xDC; opt_i2c_write(COMMAND1, &value, data->pdata->addr, data->pdata->adapt_num); } } return lx; }