static int lightsensor_onoff(u8 onoff) { u8 value = 0; #ifdef DEBUG gprintk("lightsensor_onoff = %d\n", onoff); gprintk("proximity_enable onoff = %d\n", proximity_enable); #endif if (onoff) { /*in calling, must turn on proximity sensor */ if (proximity_enable == 0) { value = 0x01; opt_i2c_write(COMMAND4, &value); value = 0x63; opt_i2c_write(COMMAND2, &value); /*OP3 : 1(operating mode) OP2 :1 (coutinuous operating mode) OP1 : 01(ALS mode) TYPE=0(auto) */ value = 0xD0; opt_i2c_write(COMMAND1, &value); /* other setting have defualt value. */ } } else { /*in calling, must turn on proximity sensor */ if (proximity_enable == 0) { value = 0x00; /*shutdown mode */ opt_i2c_write((u8) (COMMAND1), &value); } } return 0; }
static int gp2a_opt_resume(struct i2c_client *client) { struct gp2a_data *gp2a = i2c_get_clientdata(client); int i; gprintk("resume, proximity_enable:%d\n", proximity_enable); //20110702 [email protected] nothing [S] #if defined(CONFIG_LU6500) || defined(CONFIG_KS1001) || defined(CONFIG_KS1103) || defined (CONFIG_SU880) || defined (CONFIG_KU8800) || defined (CONFIG_LU8800) // nothing #else if(!proximity_enable) { /* GP2A Regs INIT SETTINGS */ for(i=1; i<=4; i++) opt_i2c_write(gp2a, (u8)(i), gp2a_original_image[i]); //20111001 [email protected] : Set Operation mode B1 for X2 New HW Revision [S] //Shutdown Mode(0x02) -> Operation Mode(ox03) Procedure 1~5 opt_i2c_write(gp2a, (u8)(REGS_CON), 0x18);//1 opt_i2c_write(gp2a, (u8)(REGS_HYS), 0x40);//2 opt_i2c_write(gp2a, (u8)(REGS_OPMOD), 0x03);//3 enable_irq(gp2a->irq);//4 msleep(2); opt_i2c_write(gp2a, (u8)(REGS_CON), 0x00);//5 //20111001 [email protected] : Set Operation mode B1 for X2 New HW Revision [E] proximity_enable = ON; } #endif //20110702 [email protected] nothing [E] return 0; }
static int lightsensor_onoff(u8 onoff, struct gp2a_data *data) { u8 value; if (onoff) { /*in calling, must turn on proximity sensor */ if (data->proximity_enabled == 0) { value = 0x01; opt_i2c_write(COMMAND4, &value); value = 0x63; opt_i2c_write(COMMAND2, &value); /*OP3 : 1(operating mode) OP2 :1 (coutinuous operating mode) OP1 : 01(ALS mode) TYPE=0(auto) */ value = 0xD0; opt_i2c_write(COMMAND1, &value); /* other setting have defualt value. */ } } else { /*in calling, must turn on proximity sensor */ if (data->proximity_enabled == 0) { value = 0x00; /*shutdown mode */ opt_i2c_write((u8) (COMMAND1), &value); } } return 0; }
static void gp2a_on(struct gp2a_data *gp2a, int type) { u8 value; printk(KERN_INFO "[OPTICAL] gp2a_on(%d)\n",type); if(type == PROXIMITY) { gprintk("[PROXIMITY] go nomal mode : power on \n"); value = 0x18; opt_i2c_write((u8)(REGS_CON),&value); value = 0x40; opt_i2c_write((u8)(REGS_HYS),&value); value = 0x03; opt_i2c_write((u8)(REGS_OPMOD),&value); gprintk("enable irq for proximity\n"); enable_irq(gp2a ->irq); value = 0x00; opt_i2c_write((u8)(REGS_CON),&value); proximity_enable =1; } if(type == LIGHT) { light_enable = ON; printk(KERN_INFO "[LIGHT_SENSOR] timer start for light sensor\n"); hrtimer_start(&gp2a->timer,ktime_set(light_init_period/2,0),HRTIMER_MODE_REL); } }
static int gp2a_opt_resume(struct i2c_client *client) { int config = 0; int err = 0; printk("[HSIL] %s\n", __func__); if(!proximity_enable) { #if defined(CONFIG_MACH_TOTORO_CTC) && (CONFIG_BOARD_REVISION >= 0x02) //twkim add proximity sensor driver to totoro_ctc #else config = GPIO_CFG(VIR_LED_EN, 0, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP, GPIO_CFG_2MA); err = gpio_tlmm_config(config, GPIO_CFG_ENABLE); if (err) printk(KERN_ERR "%s: gpio_tlmm_config(%#x)=%d\n", __func__, VIR_LED_EN, err); #endif config = GPIO_CFG(GPIO_SENSE_OUT, 0, GPIO_CFG_INPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA); err = gpio_tlmm_config(config, GPIO_CFG_ENABLE); if (err) printk(KERN_ERR "%s: gpio_tlmm_config(%#x)=%d\n", __func__, GPIO_SENSE_OUT, err); #if defined(CONFIG_MACH_TOTORO_CTC) && (CONFIG_BOARD_REVISION >= 0x02) //twkim add proximity sensor driver to totoro_ctc #else gpio_set_value(VIR_LED_EN, 1); #endif } #if 0 /* wake_up source handler */ if(proximity_enable) { value = 0x18; opt_i2c_write((u8)(REGS_CON),&value); value = 0x40; opt_i2c_write((u8)(REGS_HYS),&value); value = 0x03; opt_i2c_write((u8)(REGS_OPMOD),&value); enable_irq(gp2a->irq); value = 0x00; opt_i2c_write((u8)(REGS_CON),&value); wake_lock_timeout(&prx_wake_lock,3 * HZ); timeA = ktime_get(); printk("[%s] : wake_lock_timeout 3 Sec \n",__func__); /* if(!gpio_get_value(GPIO_PS_VOUT)) { gp2a_irq_handler(gp2a->irq,gp2a); } */ } #endif return 0; }
static ssize_t proximity_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct input_dev *input_data = to_input_dev(dev); struct gp2a_data *data = input_get_drvdata(input_data); int value = simple_strtoul(buf, NULL, 10); char input; unsigned long flags; if (value != 0 && value != 1) return count; /* Proximity power off */ if (data->enabled && !value) { disable_irq(data->irq); proximity_onoff(0); disable_irq_wake(data->irq); if (data->gp2a_led_on) data->gp2a_led_on(0); if (data->power_on) data->power_on(0); } /* proximity power on */ if (!data->enabled && value) { if (data->power_on) data->power_on(1); if (data->gp2a_led_on) data->gp2a_led_on(1); msleep(1); proximity_onoff(1); input = 0x01; opt_i2c_write((u8)(REGS_OPMOD), &input); msleep(50); enable_irq_wake(data->irq); input = gpio_get_value_cansleep(data->ps_status); input_report_abs(data->input_dev, ABS_DISTANCE, input); input_sync(data->input_dev); gprintk("[PROX] Start proximity = %d\n", input); spin_lock_irqsave(&data->prox_lock, flags); input = 0x03; opt_i2c_write((u8)(REGS_OPMOD), &input); enable_irq(data->irq); spin_unlock_irqrestore(&data->prox_lock, flags); } data->enabled = value; input_report_abs(input_data, ABS_CONTROL_REPORT, (value<<16) | data->delay); return count; }
static int gp2a_opt_resume( struct platform_device* pdev ) { struct gp2a_data *gp2a = platform_get_drvdata(pdev); u8 value; printk("[%s] : \n",__func__); /* wake_up source handler */ if(proximity_enable) { value = 0x18; opt_i2c_write((u8)(REGS_CON),&value); value = 0x40; opt_i2c_write((u8)(REGS_HYS),&value); value = 0x03; opt_i2c_write((u8)(REGS_OPMOD),&value); enable_irq(gp2a->irq); value = 0x00; opt_i2c_write((u8)(REGS_CON),&value); wake_lock_timeout(&prx_wake_lock,3 * HZ); timeA = ktime_get(); printk("[%s] : wake_lock_timeout 3 Sec \n",__func__); /* if(!gpio_get_value(GPIO_PS_VOUT)) { printk("[%s] : call irq_handler forcely \n",__func__); gp2a_irq_handler(gp2a->irq,gp2a); } */ } cur_state = STATE_INIT; light_init_check = false; if(light_enable) { gprintk("[%s] : hrtimer_start \n",__func__); hrtimer_start(&gp2a->timer,ktime_set(light_init_period/2,0),HRTIMER_MODE_REL); } return 0; }
/***************************************************************************************** * * function : gp2a_on * description : This function is power-on function for optical sensor. * * int type : Sensor type. Two values is available (PROXIMITY,LIGHT). * it support power-on function separately. * * */ int gp2a_on(struct gp2a_data *gp2a, int type) { u8 value; int err = 0; #ifdef LIGHT_SENSOR_ENABLED ktime_t light_polling_time; #endif gprintk("gp2a_on(%d)\n",type); gprintk("gp2a power on voltage up \n"); if(type == PROXIMITY) { gprintk("[PROXIMITY] go nomal mode : power on \n"); // ASD : Select switch for analog sleep function ( 0:ineffective, 1:effective ) // OCON[1:0] : Select switches for enabling/disabling VOUT terminal // ( 00:enable, 11:force to go High, 10:forcr to go Low ) value = 0x18; // 11:force to go High err = opt_i2c_write((u8)(REGS_CON),&value); if(err < 0) return err; #if defined(CONFIG_MACH_RANT3) value = 0x2F; // HYSD enable #else value = 0x40; // HYSD enable #endif err = opt_i2c_write((u8)(REGS_HYS),&value); if(err < 0) return err; // VCON : VOUT terminal output method control ( 0:normal mode, 1:interrupt mode ) // SSD : Software shutdown function ( 0:shutdown mode, 1:opteration mode ) value = 0x03; // VCON enable, SSD enable err = opt_i2c_write((u8)(REGS_OPMOD),&value); if(err < 0) return err; #if USE_INTERRUPT gprintk("enable irq for proximity\n"); enable_irq(gp2a ->irq); #if !defined(CONFIG_MACH_RANT3) set_irq_wake(gp2a->irq, 1); #endif #endif // OCON[1:0] : Select switches for enabling/disabling VOUT terminal // ( 00:enable, 11:force to go High, 10:forcr to go Low ) value = 0x00; // 00:enable err = opt_i2c_write((u8)(REGS_CON),&value); } #ifdef LIGHT_SENSOR_ENABLED if(type == LIGHT) { gprintk(KERN_INFO "[LIGHT_SENSOR] timer start for light sensor\n"); //hrtimer_start(&gp2a->timer,ktime_set(light_init_period/2,0),HRTIMER_MODE_REL); hrtimer_start(&gp2a->timer,ktime_set(0,500000000),HRTIMER_MODE_REL); light_enable = ON; } #endif return err; }
void gp2a_on(struct gp2a_data *gp2a, int type) { u8 value; int err = 0; gprintk("gp2a_on(%d)\n",type); gprintk("gp2a power on voltage up \n"); #if defined(CONFIG_MACH_VASTO) vreg_enable(vreg_proximity); #else if( board_hw_revision < 3 ) { vreg_enable(vreg_proximity); // voltage } else { gpio_set_value(VIR_LED_EN, 1); } #endif //register irq to wakeup source printk("[GP2A] register irq = %d\n",gp2a ->irq); err = set_irq_wake(gp2a ->irq, 1); // enable : 1, disable : 0 printk("[GP2A] register wakeup source = %d\n",err); if (err) printk("[GP2A] register wakeup source failed\n"); // ASD : Select switch for analog sleep function ( 0:ineffective, 1:effective ) // OCON[1:0] : Select switches for enabling/disabling VOUT terminal // ( 00:enable, 11:force to go High, 10:forcr to go Low ) value = 0x18; // 11:force to go High opt_i2c_write((u8)(REGS_CON),&value); value = 0x40; // HYSD enable opt_i2c_write((u8)(REGS_HYS),&value); // VCON : VOUT terminal output method control ( 0:normal mode, 1:interrupt mode ) // SSD : Software shutdown function ( 0:shutdown mode, 1:opteration mode ) value = 0x03; // VCON enable, SSD enable opt_i2c_write((u8)(REGS_OPMOD),&value); if(type == PROXIMITY) { gprintk("enable irq for proximity\n"); enable_irq(gp2a ->irq); } // OCON[1:0] : Select switches for enabling/disabling VOUT terminal // ( 00:enable, 11:force to go High, 10:forcr to go Low ) value = 0x00; // 00:enable opt_i2c_write((u8)(REGS_CON),&value); }
static void gp2a_work_func_prox(struct work_struct *work) { struct gp2a_data *gp2a = container_of((struct work_struct *)work, struct gp2a_data, proximity_work); unsigned char value; char result; int ret; if (gp2a->irq != 0) { disable_irq_wake(gp2a->irq); disable_irq(gp2a->irq); } /* 0 : proximity, 1 : away */ result = gpio_get_value(gp2a->pdata->p_out); gp2a->proximity_detection = !result; input_report_abs(gp2a->proximity_input_dev, ABS_DISTANCE, result); input_sync(gp2a->proximity_input_dev); printk(KERN_INFO "[GP2A] proximity value = %d \n",result); value = 0x0C; ret = opt_i2c_write(COMMAND1, &value); /*Software reset */ if (result == 0) { /* detection = Falling Edge */ if (gp2a->lightsensor_mode == 0) /* Low mode */ value = 0x23; else /* High mode */ value = 0x27; ret = opt_i2c_write(COMMAND2, &value); } else { /* none Detection */ if (gp2a->lightsensor_mode == 0) /* Low mode */ value = 0x63; else /* High mode */ value = 0x67; ret = opt_i2c_write(COMMAND2, &value); } if (gp2a->irq != 0) { enable_irq(gp2a->irq); enable_irq_wake(gp2a->irq); } value = 0xCC; ret = opt_i2c_write(COMMAND1, &value); gp2a->prox_data = result; }
static void gp2a_work_func_prox(struct work_struct *work) { struct gp2a_data *gp2a = container_of((struct work_struct *)work, struct gp2a_data, proximity_work); unsigned char value; char result; int ret; /* 0 : proximity, 1 : away */ result = gpio_get_value_cansleep(gp2a->pdata->p_out); gp2a->proximity_detection = !result; input_report_abs(gp2a->proximity_input_dev, ABS_DISTANCE, result); pr_info("%s Proximity values = %d\n", __func__, result); input_sync(gp2a->proximity_input_dev); disable_irq(gp2a->irq); value = 0x0C; ret = opt_i2c_write(COMMAND1, &value, gp2a->pdata->addr, gp2a->pdata->adapt_num); /*Software reset */ if (result == 0) { /* detection = Falling Edge */ if (gp2a->lightsensor_mode == 0) /* Low mode */ value = 0x23; else /* High mode */ value = 0x27; ret = opt_i2c_write(COMMAND2, &value, gp2a->pdata->addr, gp2a->pdata->adapt_num); } else { /* none Detection */ if (gp2a->lightsensor_mode == 0) /* Low mode */ value = 0x63; else /* High mode */ value = 0x67; ret = opt_i2c_write(COMMAND2, &value, gp2a->pdata->addr, gp2a->pdata->adapt_num); } enable_irq(gp2a->irq); value = 0xCC; ret = opt_i2c_write(COMMAND1, &value, gp2a->pdata->addr, gp2a->pdata->adapt_num); gp2a->prox_data = result; pr_debug("proximity = %d, lightsensor_mode=%d\n", result, gp2a->lightsensor_mode); }
static void gp2a_off(struct gp2a_data *gp2a, int type) { u8 value; printk(KERN_INFO "[OPTICAL] gp2a_off(%d)\n",type); if(type == PROXIMITY || type == ALL) { gprintk("[PROXIMITY] go power down mode \n"); gprintk("disable irq for proximity \n"); disable_irq(gp2a ->irq); value = 0x02; opt_i2c_write((u8)(REGS_OPMOD),&value); proximity_enable =0; proximity_value = 0; } if(type ==LIGHT) { printk("[LIGHT_SENSOR] timer cancel for light sensor\n"); hrtimer_cancel(&gp2a->timer); light_enable = OFF; cur_state = STATE_INIT; light_init_check = false; } }
int gp2a_off(struct gp2a_data *gp2a, int type) { u8 value; int err = 0; gprintk("gp2a_off(%d)\n",type); if(type == PROXIMITY || type == ALL) { #if USE_INTERRUPT gprintk("disable irq for proximity \n"); #if !defined(CONFIG_MACH_RANT3) set_irq_wake(gp2a->irq, 0); #endif disable_irq_nosync(gp2a ->irq); #endif // SSD : Software shutdown function ( 0:shutdown mode, 1:opteration mode ) value = 0x02; // VCON enable, SSD disable err = opt_i2c_write((u8)(REGS_OPMOD),&value); } #ifdef LIGHT_SENSOR_ENABLED if(type ==LIGHT) { gprintk("[LIGHT_SENSOR] timer cancel for light sensor\n"); hrtimer_cancel(&gp2a->timer); /* In case light sensor is off, set the default backlight level */ //lcdc_set_backlight_autobrightness(app_bl_level); light_enable = OFF; } #endif return err; }
static int gp2a_opt_suspend(struct i2c_client *client, pm_message_t mesg) { struct gp2a_data *gp2a = i2c_get_clientdata(client); int config = 0; int err = 0; u8 value; printk("[HSIL] %s\n", __func__); if(!proximity_enable) { config = GPIO_CFG(GPIO_PS_VOUT, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_UP, GPIO_CFG_2MA); err = gpio_tlmm_config(config, GPIO_CFG_ENABLE); if (err) printk(KERN_ERR "%s: gpio_tlmm_config(%#x)=%d\n", __func__, GPIO_PS_VOUT, err); } else { #if USE_INTERRUPT disable_irq_nosync(gp2a ->irq); #endif value = 0x02; opt_i2c_write((u8)(REGS_OPMOD),&value); printk(KERN_INFO "[%s] GP2A !!suspend mode proximity_enable \n",__FUNCTION__); } return 0; }
static int gp2a_update_threshold(struct gp2a_data *data, u8 (*selected_image)[2], u8 new_threshold, bool update_reg) { int i, err = 0; u8 set_value; pr_info("%s, new = 0x%x, thresh_diff = %d\n", __func__, new_threshold, data->thresh_diff); for (i = 0; i < COL; i++) { switch (selected_image[i][0]) { case PS_LOW_THD_L: /*PS mode LTH(Loff) for low 8bit*/ #if defined(CONFIG_MACH_KONA_SENSOR) set_value = (new_threshold-data->thresh_diff) & 0x00FF; #else set_value = new_threshold & 0x00FF; #endif break; case PS_LOW_THD_H: /*PS mode LTH(Loff) for high 8bit*/ set_value = (new_threshold & 0xFF00) >> 8; break; case PS_HIGH_THD_L: /*PS mode HTH(Lon) for low 8bit*/ #if defined(CONFIG_MACH_KONA_SENSOR) set_value = (new_threshold) & 0x00FF; #else set_value = (new_threshold+data->thresh_diff) & 0x00FF; #endif break; case PS_HIGH_THD_H: /* PS mode HTH(Lon) for high 8bit*/ set_value = ((new_threshold +data->thresh_diff) & 0xFF00) >> 8; break; default: continue; } if (update_reg) err = opt_i2c_write(selected_image[i][0], &set_value); if (err) { pr_err("%s : setting error i = %d, err=%d\n", __func__, i, err); return err; } else { selected_image[i][1] = set_value; } } return err; }
static int proximity_onoff(u8 onoff, struct gp2a_data *data) { u8 value; int i; /* unsigned char get_data[1]; */ int err = 0; pr_info("%s : proximity turn on/off = %d\n", __func__, onoff); /* already on light sensor, so must simultaneously turn on light sensor and proximity sensor */ if (onoff) { /*opt_i2c_read(COMMAND1, get_data, sizeof(get_data)); */ /*if (get_data == 0xC1) return 0; */ for (i = 0; i < COL; i++) { err = opt_i2c_write(gp2a_original_image[i][0], &gp2a_original_image[i][1], data->pdata->addr, data->pdata->adapt_num); if (err < 0) pr_err("%s : turnning on error i = %d, err=%d\n", __func__, i, err); data->lightsensor_mode = 0; } } else { /* light sensor turn on and proximity turn off */ /*opt_i2c_read(COMMAND1, get_data, sizeof(get_data)); */ /*if (get_data == 0xD1) return 0; */ if (data->lightsensor_mode) value = 0x67; /*resolution :16bit, range: *8(HIGH) */ else value = 0x63; /* resolution :16bit, range: *128(LOW) */ opt_i2c_write(COMMAND2, &value, data->pdata->addr, data->pdata->adapt_num); /* OP3 : 1(operating mode) OP2 :1(coutinuous operating mode) OP1 : 01(ALS mode) */ value = 0xD0; opt_i2c_write(COMMAND1, &value, data->pdata->addr, data->pdata->adapt_num); } return 0; }
/***************************************************************************************** * * 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. * * */ static void gp2a_work_func_prox(struct work_struct *work) { struct gp2a_data *gp2a = container_of((struct work_struct *)work, struct gp2a_data, work); char value; #ifdef PROX_MODE_B u8 reg = 0; #endif disable_irq(IRQ_GP2A_INT); value = get_ps_vout_value(); input_report_abs(gp2a->input_dev, ABS_X, value); input_sync(gp2a->input_dev); gp2a->prox_data= value; gprintk("proximity = %d\n",value); //Temp #ifdef PROX_MODE_B if(value == 1) //VO == 0 { reg = 0x40; opt_i2c_write(NOT_INT_CLR(REGS_HYS), ®); } else { reg = 0x20; opt_i2c_write(NOT_INT_CLR(REGS_HYS), ®); } reg = 0x18; opt_i2c_write(NOT_INT_CLR(REGS_CON), ®); #endif //PROX_MODE_B enable_irq(IRQ_GP2A_INT); #ifdef PROX_MODE_B reg = 0x00; opt_i2c_write(INT_CLR(REGS_CON), ®); #endif //PROX_MODE_B }
static int proximity_onoff(u8 onoff) { u8 value; int i; if (onoff) { for (i = 1 ; i < 5 ; i++) opt_i2c_write((u8)(i), &gp2a_original_image[i]); } else { #ifdef PROX_MODE_A value = 0x00; #else value = 0x02; #endif opt_i2c_write((u8)(REGS_OPMOD), &value); } return 0; }
static int gp2a_opt_resume(struct i2c_client *client) { struct gp2a_data *gp2a = i2c_get_clientdata(client); int config = 0; int err = 0; u8 value; printk("[HSIL] %s\n", __func__); if(!proximity_enable) { config = GPIO_CFG(GPIO_PS_VOUT, 0, GPIO_CFG_INPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA); err = gpio_tlmm_config(config, GPIO_CFG_ENABLE); if (err) printk(KERN_ERR "%s: gpio_tlmm_config(%#x)=%d\n", __func__, GPIO_PS_VOUT, err); } else { value = 0x18; opt_i2c_write((u8)(REGS_CON),&value); #if defined(CONFIG_MACH_RANT3) value = 0x2F; #else value = 0x40; #endif opt_i2c_write((u8)(REGS_HYS),&value); value = 0x03; opt_i2c_write((u8)(REGS_OPMOD),&value); #if USE_INTERRUPT enable_irq(gp2a->irq); #endif value = 0x00; opt_i2c_write((u8)(REGS_CON),&value); // wake_lock_timeout(&prx_wake_lock,3 * HZ); // timeA = ktime_get(); // printk("[%s] : wake_lock_timeout 3 Sec \n",__func__); } return 0; }
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 int proximity_onoff(u8 onoff) { u8 value; int i; int err = 0; #ifdef DEBUG gprintk("proximity turn on/off = %d\n", onoff); #endif /* already on light sensor, so must simultaneously turn on light sensor and proximity sensor */ if (onoff) { for (i = 0; i < COL; i++) { if (is_gp2a030a()) err = opt_i2c_write(gp2a_original_image_030a[i][0] , &gp2a_original_image_030a[i][1]); else err = opt_i2c_write(gp2a_original_image[i][0], &gp2a_original_image[i][1]); if (err < 0) printk(KERN_ERR "%s : turnning on error i = %d, err=%d\n", __func__, i, err); lightsensor_mode = 0; } } else { /* light sensor turn on and proximity turn off */ if (lightsensor_mode) value = 0x67; /*resolution :16bit, range: *8(HIGH) */ else value = 0x63; /* resolution :16bit, range: *128(LOW) */ opt_i2c_write(COMMAND2, &value); /* OP3 : 1(operating mode) OP2 :1(coutinuous operating mode) OP1 : 01(ALS mode) */ value = 0xD0; opt_i2c_write(COMMAND1, &value); } return 0; }
static long gp2a_opt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int ret = 0; short data = 0; u8 thrd = 0; switch (cmd) { case PROX_IOC_SET_CALIBRATION: { printk(KERN_INFO "[GP2A] PROX_IOC_SET_CALIBRATION\n"); if (copy_from_user(&data, (void __user *)arg, sizeof(data))) return -EFAULT; ret = proximity_open_offset(gp2a_opt_data); if (ret < 0 && ret != -ENOENT) { printk(KERN_INFO "[GP2A] proximity_open_offset() failed\n"); }else { thrd = gp2a_original_image[3][1]+(gp2a_opt_data->offset_value); opt_i2c_write(gp2a_original_image[3][0], &thrd); thrd = gp2a_original_image[5][1]+(gp2a_opt_data->offset_value); opt_i2c_write(gp2a_original_image[5][0], &thrd); } break; } case PROX_IOC_GET_CALIBRATION: { printk(KERN_INFO "[GP2A] PROX_IOC_GET_CALIBRATION\n"); data = gp2a_opt_data->offset_value; if (copy_to_user((void __user *)arg, &data, sizeof(data))) return -EFAULT; break; } default: printk(KERN_ERR "Unknown IOCTL command"); ret = -ENOTTY; break; } return ret; }
static int lightsensor_onoff(u8 onoff, struct gp2a_data *data) { u8 value; #ifdef DEBUG pr_info(KERN_INFO "%s : light_sensor onoff = %d\n", __func__, onoff); data->proximity_enabled); #endif if (onoff) { /*in calling, must turn on proximity sensor */ if (data->proximity_enabled == 0) { value = 0x01; opt_i2c_write(COMMAND4, &value, data->pdata->addr, data->pdata->adapt_num); value = 0x63; opt_i2c_write(COMMAND2, &value, data->pdata->addr, data->pdata->adapt_num); /*OP3 : 1(operating mode) OP2 :1 (coutinuous operating mode) OP1 : 01(ALS mode) TYPE=0(auto) */ value = 0xD0; opt_i2c_write(COMMAND1, &value, data->pdata->addr, data->pdata->adapt_num); /* other setting have defualt value. */ } } else { /*in calling, must turn on proximity sensor */ if (data->proximity_enabled == 0) { value = 0x00; /*shutdown mode */ opt_i2c_write((u8) (COMMAND1), &value, data->pdata->addr, data->pdata->adapt_num); } } return 0; }
void gp2a_on(struct gp2a_data *gp2a) { int i; if(proximity_enable == OFF) { gprintk("gp2a power on\n"); #if defined(CONFIG_LU6500) || defined(CONFIG_KS1001) gp2a_power_control(ON); msleep(5); #endif proximity_enable = ON; //20111001 [email protected] : Set Operation mode B1 for X2 New HW Revision [S] //Shutdown Mode(0x02) -> Operation Mode(ox03) Procedure 1~5 opt_i2c_write(gp2a, (u8)(REGS_CON), 0x18);//1 opt_i2c_write(gp2a, (u8)(REGS_HYS), 0x40);//2 opt_i2c_write(gp2a, (u8)(REGS_OPMOD), 0x03);//3 enable_irq(gp2a->irq);//4 msleep(2); opt_i2c_write(gp2a, (u8)(REGS_CON), 0x00);//5 //20111001 [email protected] : Set Operation mode B1 for X2 New HW Revision [E] gp2a_read_forcely(gp2a); } }
static int gp2a_update_threshold(u8 (*selected_image)[2], unsigned long new_threshold, bool update_reg) { int i, err = 0; u8 set_value; for (i = 0; i < COL; i++) { switch (selected_image[i][0]) { case PS_LOW_THD_L: /*PS mode LTH(Loff) for low 8bit*/ set_value = new_threshold & 0x00FF; break; case PS_LOW_THD_H: /*PS mode LTH(Loff) for high 8bit*/ set_value = (new_threshold & 0xFF00) >> 8; break; case PS_HIGH_THD_L: /*PS mode HTH(Lon) for low 8bit*/ set_value = (new_threshold+1) & 0x00FF; break; case PS_HIGH_THD_H: /* PS mode HTH(Lon) for high 8bit*/ set_value = ((new_threshold+1) & 0xFF00) >> 8; break; default: continue; } if (update_reg) err = opt_i2c_write(selected_image[i][0], &set_value); if (err) { pr_err("%s : setting error i = %d, err=%d\n", __func__, i, err); return err; } else selected_image[i][1] = set_value; } return err; }
void gp2a_off(struct gp2a_data *gp2a, int type) { u8 value; int err = 0; #if defined(CONFIG_MACH_TOTORO_CTC) && (CONFIG_BOARD_REVISION >= 0x02) //twkim add proximity sensor driver to totoro_ctc vreg_disable(vreg_proximity); // voltage #else if( board_hw_revision < 3 ) { vreg_disable(vreg_proximity); // voltage } else { gpio_set_value(VIR_LED_EN, 0); } #endif gprintk("gp2a_off voltage down(%d)\n",type); //delete irq from wakeup source printk("[GP2A] unregister irq = %d\n",gp2a ->irq); err = set_irq_wake(gp2a ->irq, 0); // enable : 1, disable : 0 printk("[GP2A] register wakeup source = %d\n",err); if (err) printk("[GP2A] register wakeup source failed\n"); gprintk("gp2a power off \n"); if(type == PROXIMITY || type==ALL) { gprintk("disable irq for proximity \n"); disable_irq_nosync(gp2a ->irq); } // SSD : Software shutdown function ( 0:shutdown mode, 1:opteration mode ) value = 0x02; // VCON enable, SSD disable opt_i2c_write((u8)(REGS_OPMOD),&value); #if defined(CONFIG_MACH_TOTORO_CTC) && (CONFIG_BOARD_REVISION >= 0x02) //twkim add proximity sensor driver to totoro_ctc gp2a_gpio_set(DISABLE); #endif }
void gp2a_off(struct gp2a_data *gp2a) { gprintk("gp2a_off\n"); if(proximity_enable == ON) { gprintk("disable irq for proximity \n"); //20110921 [email protected] : for Phone Call and First Status in Framework[S] wake_lock_timeout(&gp2a_wake_lock, 3 * HZ); input_report_abs(gp2a->input_dev,ABS_DISTANCE, FAR); input_sync(gp2a->input_dev); mdelay(1); //20110921 [email protected] : for Phone Call and First Status in Framework[E] //20111001 [email protected] : Set Operation mode B1 for X2 New HW Revision [S] //Operation Mode(0x03) -> Shutdown Mode(0x02) disable_irq_nosync(gp2a->irq); opt_i2c_write(gp2a, (u8)(REGS_OPMOD), 0x02); //20111001 [email protected] : Set Operation mode B1 for X2 New HW Revision [E] proximity_enable = OFF; } }
static int gp2a_opt_suspend(struct i2c_client *client, pm_message_t state) { struct gp2a_data *gp2a = i2c_get_clientdata(client); gprintk("suspend, proximity_enable:%d\n", proximity_enable); //20110702 [email protected] nothing [S] #if defined(CONFIG_LU6500) || defined(CONFIG_KS1001) || defined(CONFIG_KS1103) || defined (CONFIG_SU880) || defined (CONFIG_KU8800) || defined (CONFIG_LU8800) // nothing #else if(proximity_enable) { //20111001 [email protected] : Set Operation mode B1 for X2 New HW Revision [S] //Operation Mode(0x03) -> Shutdown Mode(0x02) disable_irq_nosync(gp2a->irq); opt_i2c_write(gp2a, (u8)(REGS_OPMOD), 0x02); //20111001 [email protected] : Set Operation mode B1 for X2 New HW Revision [E] proximity_enable = OFF; } #endif //20110702 [email protected] nothing [E] return 0; }
static int gp2a_opt_probe(struct i2c_client *client, const struct i2c_device_id *id) { int err = 0; int i; #if USE_INTERRUPT int irq; #endif int config; struct gp2a_data *gp2a; #ifdef STM_DEBUG printk(KERN_INFO "%s\n",__FUNCTION__); #endif #if defined(CONFIG_MACH_TOTORO_CTC) && (CONFIG_BOARD_REVISION >= 0x02) //twkim add proximity sensor driver to totoro_ctc { vreg_proximity = vreg_get(0, "ldo9"); //twkim fixed pmic set if (IS_ERR(vreg_proximity)) { printk("===== [PROXIMITY] proximity IS_ERR TEST =====\n"); return PTR_ERR(vreg_proximity); } #if defined(CONFIG_MACH_TOTORO_CTC) && (CONFIG_BOARD_REVISION >= 0x02) //twkim add proximity sensor driver to totoro_ctc vreg_set_level(vreg_proximity, OUT2800mV); // set to 3.0V voltage twkim 12 -> 10 to set 2.85V -> 2.6v gp2a_gpio_set(ENABLE); #else vreg_set_level(vreg_proximity, OUT2850mV); // set to 3.0V voltage twkim 12 -> 10 to set 2.85V #endif vreg_enable(vreg_proximity); // voltage } #else if( board_hw_revision < 3 ) { vreg_proximity = vreg_get(0, "ldo19"); if (IS_ERR(vreg_proximity)) { printk("===== [PROXIMITY] proximity IS_ERR TEST =====\n"); return PTR_ERR(vreg_proximity); } vreg_set_level(vreg_proximity, 12); // set to 3.0V voltage vreg_enable(vreg_proximity); // voltage } else { gpio_set_value(VIR_LED_EN, 1); } #endif if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { printk(KERN_INFO "[GP2A] i2c_check_functionality error\n"); err = -ENODEV; goto exit; } if ( !i2c_check_functionality(client->adapter,I2C_FUNC_SMBUS_BYTE_DATA) ) { printk(KERN_INFO "[GP2A] byte op is not permited.\n"); goto exit; } /* OK. For now, we presume we have a valid client. We now create the client structure, even though we cannot fill it completely yet. */ if (!(gp2a = kzalloc(sizeof(struct gp2a_data), GFP_KERNEL))) { err = -ENOMEM; goto exit; } memset(gp2a, 0, sizeof(struct gp2a_data)); gp2a->client = client; i2c_set_clientdata(client, gp2a); opt_i2c_client = client; if (i2c_smbus_read_byte(client) < 0) { printk(KERN_ERR "[GP2A] i2c_smbus_read_byte error!!\n"); goto exit_kfree; } else { printk("GP2A Device detected!\n"); } printk("[%s] slave addr = %x\n", __func__, client->addr); /* Input device Settings */ if(USE_INPUT_DEVICE) { gp2a->input_dev = input_allocate_device(); if (gp2a->input_dev == NULL) { pr_err("Failed to allocate input device\n"); return -ENOMEM; } gp2a->input_dev->name = "proximity_sensor"; set_bit(EV_SYN,gp2a->input_dev->evbit); set_bit(EV_ABS,gp2a->input_dev->evbit); input_set_abs_params(gp2a->input_dev, ABS_DISTANCE, 0, 1, 0, 0); err = input_register_device(gp2a->input_dev); if (err) { pr_err("Unable to register %s input device\n", gp2a->input_dev->name); input_free_device(gp2a->input_dev); kfree(gp2a); return -1; } } #if USE_INTERRUPT /* WORK QUEUE Settings */ gp2a_wq = create_singlethread_workqueue("gp2a_wq"); if (!gp2a_wq) return -ENOMEM; INIT_WORK(&gp2a->work_prox, gp2a_work_func_prox); gprintk("Workqueue Settings complete\n"); #endif /* misc device Settings */ err = misc_register(&proximity_device); if(err) { pr_err(KERN_ERR "misc_register failed - prox \n"); } /* wake lock init */ wake_lock_init(&prx_wake_lock, WAKE_LOCK_SUSPEND, "prx_wake_lock"); /* set sysfs for light sensor */ proxsensor_class = class_create(THIS_MODULE, "proxsensor"); if (IS_ERR(proxsensor_class)) pr_err("Failed to create class(proxsensor)!\n"); switch_cmd_dev = device_create(proxsensor_class, NULL, 0, NULL, "switch_cmd"); if (device_create_file(switch_cmd_dev, &dev_attr_proxsensor_file_state) < 0) pr_err("Failed to create device file(%s)!\n", dev_attr_proxsensor_file_state.attr.name); dev_set_drvdata(switch_cmd_dev,gp2a); /* ktime init */ timeA = ktime_set(0,0); timeB = ktime_set(0,0); /* gpio config */ config = GPIO_CFG(GPIO_SENSE_OUT, 0, GPIO_CFG_INPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA); err = gpio_tlmm_config(config, GPIO_CFG_ENABLE); if (err) printk(KERN_ERR "%s: gpio_tlmm_config(%#x)=%d\n", __func__, GPIO_SENSE_OUT, err); /* GP2A Regs INIT SETTINGS */ for(i=1;i<5;i++) { opt_i2c_write((u8)(i),&gp2a_original_image[i]); } mdelay(2); #if USE_INTERRUPT /* INT Settings */ irq = gpio_to_irq(GPIO_SENSE_OUT); gp2a->irq = -1; set_irq_type(irq, IRQ_TYPE_EDGE_BOTH); err = request_irq(irq, gp2a_irq_handler, IRQF_DISABLED, "gp2a_int", gp2a); if (err) { printk("[GP2A] request_irq failed for gp2a\n"); goto exit_kfree; } printk("[GP2A] register irq = %d\n",irq); err = set_irq_wake(irq, 1); printk("[GP2A] register wakeup source = %d\n",err); if (err) printk("[GP2A] register wakeup source failed\n"); gp2a->irq = irq; gprintk("INT Settings complete\n"); #endif // maintain power-down mode before using sensor gp2a_off(gp2a,ALL); //++ // test for sensor /* printk("[GP2A] curr prox value = %d\n", gpio_get_value(GPIO_SENSE_OUT)); gp2a_on(gp2a,PROXIMITY); printk("[GP2A] curr prox value = %d\n", gpio_get_value(GPIO_SENSE_OUT)); //-- // maintain power-down mode before using sensor //ESD test sleep gp2a_off(gp2a,ALL); */ printk("gp2a_opt_probe is OK!!\n"); return 0; exit_kfree: kfree(gp2a); exit: return err; }
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); }