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
Beispiel #3
0
}

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);
Beispiel #5
0
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
*/
Beispiel #7
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
/*                                                                                                                                  
                                   
                                     
             
                                                     
             
  
      
*/
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;
}