static int apds9130_enable_ps_sensor(struct i2c_client *client, int val) { struct apds9130_data *data = i2c_get_clientdata(client); printk(KERN_INFO"enable ps sensor ( %d)\n", val); /* APDS9130_DISABLE_PS (0) = Disable PS */ /* APDS9130_ENABLE_PS_WITH_INT (1) = Enable PS with interrupt enabled */ if(val == APDS9130_ENABLE_PS_WITH_INT ) { #if defined(APDS9130_PROXIMITY_CAL) data->cross_talk = apds9130_read_crosstalk_data_fs(); #ifdef CONFIG_LEDS_LP5521 if(data->cross_talk <= 10 || data->cross_talk>870) #else if(data->cross_talk < 0 || data->cross_talk>870) #endif { printk(KERN_INFO"[%s] FROM FS data->crosstalk = %d", __func__, data->cross_talk); data->cross_talk = PS_DEFAULT_CROSS_TALK; } printk(KERN_INFO"%s Cross_talk : %d\n", __FUNCTION__, data->cross_talk); apds9130_Set_PS_Threshold_Adding_Cross_talk(client, data->cross_talk); printk(KERN_INFO"%s apds9130_Set_PS_Threshold_Adding_Cross_talk\n", __FUNCTION__); printk(KERN_INFO"%s apds9130_Set_PS_Threshold_Adding_Cross_talk = %d\n", __FUNCTION__,data->cross_talk); #endif //turn on p sensor data->enable_ps_sensor = val; apds9130_set_enable(client,0); /* Power Off */ apds9130_set_pilt(client, 0); // init threshold for proximity apds9130_set_piht(client, data->ps_threshold); //[LGSI_SP4_BSP][[email protected]] add calibrated threshold //[LGSI_SP4_BSP_BEGIN][[email protected]] Report the Far Detection evertytime when u enable the sensor 07-11-2012 input_report_abs(data->input_dev_ps, ABS_DISTANCE, PROX_INPUT_FAR);/* NEAR-to-FAR detection */ input_sync(data->input_dev_ps); //[LGSI_SP4_BSP_END][[email protected]] Report the Far Detection evertytime when u enable the sensor apds9130_set_enable(client, 0x2D); /* enable PS interrupt */ } else { apds9130_set_enable(client, 0); data->enable_ps_sensor = 0; } return 0; }
#ifdef CONFIG_PM static int apds9130_suspend(struct i2c_client *client, pm_message_t mesg) { #if 1 #else struct apds9130_data *data = i2c_get_clientdata(client); if(data->sw_mode == PROX_STAT_SHUTDOWN) return 0; apds9130_set_enable(client, 0); apds9130_set_command(client, 2); __cancel_delayed_work(&data->dwork); flush_delayed_work(&data->dwork); flush_workqueue(apds9130_workqueue); data->sw_mode = PROX_STAT_SHUTDOWN; disable_irq(client->irq); /* err = pdata->power(0); if(err < 0) { printk(KERN_INFO "%s, Proximity Power Off Fail in susped\n",__func__); return err; } */ irq_set_irq_wake(client->irq, 0); if(NULL != apds9130_workqueue){ destroy_workqueue(apds9130_workqueue); printk(KERN_INFO "%s, Destroy workqueue\n",__func__); apds9130_workqueue = NULL; } #endif
} static int __devexit apds9130_remove(struct i2c_client *client) { struct apds9130_data *data = i2c_get_clientdata(client); /* Power down the device */ apds9130_set_enable(client, 0); sysfs_remove_group(&client->dev.kobj, &apds9130_attr_group); disable_irq_wake(client->irq); free_irq(client->irq, client); input_unregister_device(data->input_dev_ps); input_free_device(data->input_dev_ps); wake_lock_destroy(&data->ps_wlock); // mutex_destroy(&data->update_lock); // kfree(data);
} static int __devexit apds9130_remove(struct i2c_client *client) { struct apds9130_data *data = i2c_get_clientdata(client); /* Power down the device */ apds9130_set_enable(client, 0); sysfs_remove_group(&client->dev.kobj, &apds9130_attr_group); disable_irq_wake(client->irq); free_irq(client->irq, client); input_unregister_device(data->input_dev_ps); input_free_device(data->input_dev_ps); wake_lock_destroy(&data->ps_wlock); //[LGSI_SP4_BSP_BEGIN][[email protected]] 30-11-2012 Destroy the mutex after its usage mutex_destroy(&data->update_lock); //[LGSI_SP4_BSP_END][[email protected]] kfree(data);
static int apds9130_enable_ps_sensor(struct i2c_client *client, int val) { struct apds9130_data *data = i2c_get_clientdata(client); printk(KERN_INFO"enable ps sensor ( %d)\n", val); /* APDS9130_DISABLE_PS (0) = Disable PS */ /* APDS9130_ENABLE_PS_WITH_INT (1) = Enable PS with interrupt enabled */ if(val == APDS9130_ENABLE_PS_WITH_INT ) { #if defined(APDS9130_PROXIMITY_CAL) data->cross_talk = apds9130_read_crosstalk_data_fs(); if(data->cross_talk < 0 || data->cross_talk>870) data->cross_talk = PS_DEFAULT_CROSS_TALK; printk(KERN_INFO"%s Cross_talk : %d\n", __FUNCTION__, data->cross_talk); apds9130_Set_PS_Threshold_Adding_Cross_talk(client, data->cross_talk); printk(KERN_INFO"%s apds9130_Set_PS_Threshold_Adding_Cross_talk\n", __FUNCTION__); printk(KERN_INFO"%s apds9130_Set_PS_Threshold_Adding_Cross_talk = %d\n", __FUNCTION__,data->cross_talk); #endif //turn on p sensor data->enable_ps_sensor = val; apds9130_set_enable(client,0); /* Power Off */ apds9130_set_pilt(client, 0); // init threshold for proximity apds9130_set_piht(client, data->ps_threshold); // // input_report_abs(data->input_dev_ps, ABS_DISTANCE, PROX_INPUT_FAR);/* NEAR-to-FAR detection */ input_sync(data->input_dev_ps); // apds9130_set_enable(client, 0x2D); /* enable PS interrupt */ } else { apds9130_set_enable(client, 0); data->enable_ps_sensor = 0; } return 0; }
*/ static int apds9130_init_client(struct i2c_client *client) { struct apds9130_data *data = i2c_get_clientdata(client); int err; int id; err = apds9130_set_enable(client, 0); if (err < 0) return err; data->pDrive = APDS9130_PDRVIE_100MA; id = i2c_smbus_read_byte_data(client, CMD_BYTE|APDS9130_ID_REG); if (id == 0x39) { printk(KERN_INFO"APDS-9130\n"); } else { printk(KERN_INFO"Not APDS-9130 %x\n", id); return -EIO; } err = apds9130_set_ptime(client, 0xFF); // 2.72ms Prox integration time if (err < 0) return err; err = apds9130_set_wtime(client, 0xDC); // 100ms Wait time for POLL_MEDIUM if (err < 0) return err; err = apds9130_set_ppcount(client, APDS9130_PS_PULSE_NUMBER); if (err < 0) return err; err = apds9130_set_config(client, 0); // no long wait if (err < 0) return err; err = apds9130_set_control(client, APDS9130_PDRVIE_100MA|APDS9130_PRX_IR_DIOD|APDS9130_PGAIN_2X); // 2012.10.10 PGAIN 4x-> 2x chkim. if (err < 0) return err; err = apds9130_set_pilt(client, 0); // init threshold for proximity if (err < 0) return err; err = apds9130_set_piht(client, APDS9130_PS_DETECTION_THRESHOLD); if (err < 0) return err; err = apds9130_set_pers(client, APDS9130_PPERS_2); // 2 consecutive Interrupt persistence if (err < 0) return err; // sensor is in disabled mode but all the configurations are preset /* Temp block the below code as no need to set cross talk threshold during proximity OFF state [LGSI_SP4_BSP][[email protected]] #if defined(APDS9130_PROXIMITY_CAL) err = apds9130_set_enable(client,0); if(err < 0){ printk(KERN_INFO "%s, enable set Fail\n",__func__); return err; } #endif */
*/ static int apds9130_init_client(struct i2c_client *client) { struct apds9130_data *data = i2c_get_clientdata(client); int err; int id; err = apds9130_set_enable(client, 0); if (err < 0) return err; data->pDrive = APDS9130_PDRVIE_100MA; id = i2c_smbus_read_byte_data(client, CMD_BYTE|APDS9130_ID_REG); if (id == 0x39) { printk(KERN_INFO"APDS-9130\n"); } else { printk(KERN_INFO"Not APDS-9130 %x\n", id); return -EIO; } err = apds9130_set_ptime(client, 0xFF); // 2.72ms Prox integration time if (err < 0) return err; err = apds9130_set_wtime(client, 0xDC); // 100ms Wait time for POLL_MEDIUM if (err < 0) return err; err = apds9130_set_ppcount(client, APDS9130_PS_PULSE_NUMBER); if (err < 0) return err; err = apds9130_set_config(client, 0); // no long wait if (err < 0) return err; err = apds9130_set_control(client, APDS9130_PDRVIE_100MA|APDS9130_PRX_IR_DIOD|APDS9130_PGAIN_2X); // 2012.10.10 PGAIN 4x-> 2x chkim. if (err < 0) return err; err = apds9130_set_pilt(client, 0); // init threshold for proximity if (err < 0) return err; err = apds9130_set_piht(client, APDS9130_PS_DETECTION_THRESHOLD); if (err < 0) return err; err = apds9130_set_pers(client, APDS9130_PPERS_2); // 2 consecutive Interrupt persistence if (err < 0) return err; // sensor is in disabled mode but all the configurations are preset /* */
static int apds9130_suspend(struct i2c_client *client, pm_message_t mesg) { struct apds9130_data *data = i2c_get_clientdata(client); printk("[ProximitySensor] %s [%x][%d]\n", __func__, data->enable, data->irq_wake); disable_irq(data->irq); if( !enable_irq_wake(data->irq) ) data->irq_wake = 1; flush_delayed_work_sync(&data->dwork); if( data->enable & 0x20 ) { apds9130_set_enable(client, 0x25); } else { apds9130_set_enable(client, 0); } return 0; }
/* * Initialization function */ static int apds9130_init_client(struct i2c_client *client) { int err; int id; err = apds9130_set_enable(client, 0); if (err < 0) return err; id = i2c_smbus_read_byte_data(client, CMD_BYTE|APDS9130_ID_REG); if (id == 0x39) { printk("[ProximitySensor] APDS-9130\n"); } else { printk("[ProximitySensor_E] Not APDS-9130 %x\n", id); return -EIO; } err = apds9130_set_ptime(client, 0xFF); // 2.72ms Prox integration time if (err < 0) return err; err = apds9130_set_wtime(client, 0xDC); // 100ms Wait time for POLL_MEDIUM if (err < 0) return err; err = apds9130_set_ppcount(client, APDS9130_PS_PULSE_NUMBER); if (err < 0) return err; err = apds9130_set_config(client, 0); // no long wait if (err < 0) return err; #if defined(CONFIG_MACH_LGE_L9II_OPEN_EU) err = apds9130_set_control(client, APDS9130_PDRVIE_100MA|APDS9130_PRX_IR_DIOD|APDS9130_PGAIN_2X); #else err = apds9130_set_control(client, APDS9130_PDRVIE_100MA|APDS9130_PRX_IR_DIOD|APDS9130_PGAIN_4X); #endif if (err < 0) return err; err = apds9130_set_pilt(client, 1023); // to force first Near-to-Far interrupt if (err < 0) return err; err = apds9130_set_piht(client, 0); if (err < 0) return err; err = apds9130_set_pers(client, APDS9130_PPERS_2); // 2 consecutive Interrupt persistence if (err < 0) return err; // sensor is in disabled mode but all the configurations are preset return 0; }
} static int apds9130_resume(struct i2c_client *client) { #if 1 #else struct apds9130_data *data = i2c_get_clientdata(client); int ret; int err = 0; if(apds9130_workqueue == NULL) { apds9130_workqueue = create_workqueue("proximity"); if(NULL == apds9130_workqueue) return -ENOMEM; } printk(KERN_INFO"apds9190_resume \n"); if(data->sw_mode == PROX_STAT_OPERATING) return 0; enable_irq(client->irq); mdelay(50); err = apds9130_set_enable(client, 0x2D); if(err < 0){ printk(KERN_INFO "%s, enable set Fail\n",__func__); return -1; } data->sw_mode = PROX_STAT_OPERATING; ret = irq_set_irq_wake(client->irq, 1); if(ret) irq_set_irq_wake(client->irq, 0); apds9130_set_command(client, 0); #endif
static int apds9130_Run_Cross_talk_Calibration(struct i2c_client *client) { struct apds9130_data *data = i2c_get_clientdata(client); unsigned int sum_of_pdata = 0,temp_pdata[20]; unsigned int ret=0,i=0,j=0,ArySize = 20,cal_check_flag = 0; unsigned int old_enable = 0; printk(KERN_INFO"%s Enter \n", __FUNCTION__); old_enable = data->enable; RE_CALIBRATION: sum_of_pdata = 0; apds9130_set_enable(client, 0x0D); msleep(50); for(i =0;i<20;i++) { temp_pdata[i] = i2c_smbus_read_word_data(client, CMD_WORD|APDS9130_PDATAL_REG); mdelay(6); } for(i=0; i<ArySize-1; i++) for(j=i+1; j<ArySize; j++) if(temp_pdata[i] > temp_pdata[j]) apds9130_swap(temp_pdata+i, temp_pdata+j); for (i = 5;i<15;i++) sum_of_pdata = sum_of_pdata + temp_pdata[i]; data->cross_talk = sum_of_pdata/10; if (data->cross_talk>870) { if (cal_check_flag == 0) { cal_check_flag = 1; goto RE_CALIBRATION; } else { apds9130_set_enable(client,0x00); apds9130_set_enable(client,old_enable); return -1; } } #ifdef CONFIG_LEDS_LP5521 data->ps_threshold = 100 + data->cross_talk; data->ps_hysteresis_threshold = data->ps_threshold - 40; #else data->ps_threshold = 150 + data->cross_talk; data->ps_hysteresis_threshold = data->ps_threshold - 60; #endif ret = apds9130_backup_crosstalk_data_fs(data->cross_talk); if(ret < 0) { printk(KERN_ERR"[%s] apds9130_backup_crosstalk_data_fs fail ",__func__); return -1; } printk(KERN_INFO"%s threshold : %d\n", __FUNCTION__, data->ps_threshold); printk(KERN_INFO"%s Hysteresis_threshold : %d\n",__FUNCTION__, data->ps_hysteresis_threshold); apds9130_set_enable(client,0x00); apds9130_set_enable(client,old_enable); printk(KERN_INFO"%s Leave\n", __FUNCTION__); return data->cross_talk; }
static int apds9130_Run_Cross_talk_Calibration(struct i2c_client *client) { struct apds9130_data *data = i2c_get_clientdata(client); int pdata[20], total_pdata = 0; int i, j, temp; bool isCal = false; printk("===================================================\n%s: START proximity sensor calibration\n", __func__); // proximity enable & wait apds9130_set_enable(client, 0x0D); RE_CALIBRATION: // read 20 data to calculate the average pdata at no-object state for(i=0; i<20; i++) { pdata[i] = i2c_smbus_read_word_data(client, CMD_WORD|APDS9130_PDATAL_REG); mdelay(5); } // pdata sorting for(i=0; i<19; i++) { for(j=i+1; j<20; j++) { if(pdata[i] > pdata[j]) { temp = pdata[i]; pdata[i] = pdata[j]; pdata[j] = temp; } } } // calculate the cross-talk using central 10 data for(i=5; i<15; i++) { printk("pdata = %d\n", pdata[i]); total_pdata += pdata[i]; } // store cross_talk value into the apds9190_data structure data->cross_talk = total_pdata / 10; data->avg_cross_talk = data->cross_talk; // check if the calibrated cross_talk data is valid or not if(data->cross_talk > MAX_CROSS_TALK) { printk("[ProximitySensor] %s: invalid calibrated data\n", __func__); if(!isCal) { printk("[ProximitySensor] %s: RE_CALIBRATION start\n", __func__); isCal = true; total_pdata = 0; goto RE_CALIBRATION; } else { printk("[ProximitySensor] %s: CALIBRATION FAIL -> cross_talk is set to DEFAULT\n", __func__); data->cross_talk = DEFAULT_CROSS_TALK; } } // proximity disable apds9130_set_enable(client, 0x00); printk("[ProximitySensor] %s: total_pdata = %d & cross_talk = %d\n%s: FINISH proximity sensor calibration\n===================================================\n", __func__, total_pdata, data->cross_talk, __func__); return data->cross_talk; }
static int apds9130_enable_ps_sensor(struct i2c_client *client, int val) { struct apds9130_data *data = i2c_get_clientdata(client); printk("[ProximitySensor] %s(%d)\n", __func__, val); if ((val != APDS9130_DISABLE_PS) && (val != APDS9130_ENABLE_PS_WITH_INT) && (val != APDS9130_ENABLE_PS_NO_INT)) { printk("[ProximitySensor_E] %s : invalid value(%d)\n", __func__, val); return -1; } /* APDS9130_DISABLE_PS (0) = Disable PS */ /* APDS9130_ENABLE_PS_WITH_INT (1) = Enable PS with interrupt enabled */ /* APDS9130_ENABLE_PS_NO_INT (2) = Enable PS without interrupt enabled */ if(val == APDS9130_ENABLE_PS_WITH_INT || val == APDS9130_ENABLE_PS_NO_INT) { //turn on p sensor data->enable_ps_sensor = val; apds9130_set_enable(client,0); /* Power Off */ apds9130_set_pilt(client, 1023); // to force first Near-to-Far interrupt apds9130_set_piht(client, 0); /* */ apds9130_set_pers(client, APDS9130_PPERS_0); if (val == APDS9130_ENABLE_PS_WITH_INT) { apds9130_set_enable(client, 0x2D); /* enable PS interrupt */ /* * If work is already scheduled then subsequent schedules will not * change the scheduled time that's why we have to cancel it first. */ __cancel_delayed_work(&data->ps_dwork); flush_delayed_work(&data->ps_dwork); } else { apds9130_set_enable(client, 0x0D); /* no PS interrupt */ /* * If work is already scheduled then subsequent schedules will not * change the scheduled time that's why we have to cancel it first. */ __cancel_delayed_work(&data->ps_dwork); flush_delayed_work(&data->ps_dwork); schedule_delayed_work(&data->ps_dwork, msecs_to_jiffies(data->ps_poll_delay)); } } else { apds9130_set_enable(client, 0); data->enable_ps_sensor = 0; /* * If work is already scheduled then subsequent schedules will not * change the scheduled time that's why we have to cancel it first. */ __cancel_delayed_work(&data->ps_dwork); flush_delayed_work(&data->ps_dwork); } return 0; }