Exemplo n.º 1
0
/* PS interrupt routine */
static void apds9130_work_handler(struct work_struct *work)
{
	struct apds9130_data *data = container_of(work, struct apds9130_data, dwork.work);
	struct i2c_client *client=data->client;
	int status;
	int enable;


	if(wake_lock_active(&data->ps_wlock))
		wake_unlock(&data->ps_wlock);
	wake_lock_timeout(&data->ps_wlock, 2 * HZ);


	status = i2c_smbus_read_byte_data(client, CMD_BYTE|APDS9130_STATUS_REG);
	enable = i2c_smbus_read_byte_data(client, CMD_BYTE|APDS9130_ENABLE_REG);

	i2c_smbus_write_byte_data(client, CMD_BYTE|APDS9130_ENABLE_REG, 1);	/* disable 9130 first */

	printk(KERN_INFO"status = %x\n", status);

	if ((status & enable & 0x30) == 0x30) {
		/* both PS and ALS are interrupted - never happened*/

		if ( (status&0x40) != 0x40 ) // no PSAT bit set
			apds9130_change_ps_threshold(client);
		else {
			if (data->ps_detection == 1) {
				apds9130_change_ps_threshold(client);
			}
			else {
				printk(KERN_INFO"Triggered by background ambient noise\n");
			}
		}

		apds9130_set_command(client, 2);	/* 2 = CMD_CLR_PS_ALS_INT */
	}
	else if ((status & enable & 0x20) == 0x20) {
		/* only PS is interrupted */

		if ( (status&0x40) != 0x40 ) // no PSAT bit set
			apds9130_change_ps_threshold(client);	// far-to-near
		else {
			if (data->ps_detection == 1) {
				apds9130_change_ps_threshold(client); // near-to-far
			}
			else {
				printk(KERN_INFO"Triggered by background ambient noise\n");
			}
		}

		apds9130_set_command(client, 0);	/* 0 = CMD_CLR_PS_INT */
	}
	else if ((status & enable & 0x10) == 0x10) {
		/* only ALS is interrupted - will never happened*/

		apds9130_set_command(client, 1);	/* 1 = CMD_CLR_ALS_INT */
	}

	i2c_smbus_write_byte_data(client, CMD_BYTE|APDS9130_ENABLE_REG, data->enable);
}
Exemplo n.º 2
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
Exemplo n.º 3
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
/* PS polling routine */
static void apds9130_ps_polling_work_handler(struct work_struct *work)
{
	struct apds9130_data *data = container_of(work, struct apds9130_data, ps_dwork.work);
	struct i2c_client *client=data->client;
	int status;

	status = i2c_smbus_read_byte_data(client, CMD_BYTE|APDS9130_STATUS_REG);
	data->ps_data = i2c_smbus_read_word_data(client, CMD_WORD|APDS9130_PDATAL_REG);
		
	// check PS under bright light
	if ( (data->ps_data > data->ps_threshold) && (data->ps_detection == 0) && ((status&0x40)==0x00) ) {
		/* far-to-near detected */
		data->ps_detection = 1;

		input_report_abs(data->input_dev_ps, ABS_DISTANCE, 0);/* FAR-to-NEAR detection */
		input_sync(data->input_dev_ps);

		printk("[ProximitySensor] far-to-NEAR\n");
	} 
	else if ( (data->ps_data < data->ps_hysteresis_threshold) && (data->ps_detection == 1) && ((status&0x40)==0x00) ) {	
		// PS was previously in far-to-near condition
		/* near-to-far detected */
		data->ps_detection = 0;

		input_report_abs(data->input_dev_ps, ABS_DISTANCE, 1);/* NEAR-to-FAR detection */
		input_sync(data->input_dev_ps);

		printk("[ProximitySensor] near-to-FAR\n");
	}
	else {
		printk("* Triggered by background ambient noise\n");
	}

	if ( (status&0x40) == 0x40 ) {	// need to clear psat bit if it is set
		apds9130_set_command(client, 0);	/* 0 = CMD_CLR_PS_INT */
	}
	
	schedule_delayed_work(&data->ps_dwork, msecs_to_jiffies(data->ps_poll_delay));	// restart timer
}
/* PS interrupt routine */
static void apds9130_work_handler(struct work_struct *work)
{
	struct apds9130_data *data = container_of(work, struct apds9130_data, dwork.work);
	struct i2c_client *client=data->client;
	int status;
	int enable;
    int err = 0;

	status = i2c_smbus_read_byte_data(client, CMD_BYTE|APDS9130_STATUS_REG);
	enable = i2c_smbus_read_byte_data(client, CMD_BYTE|APDS9130_ENABLE_REG);

	err = i2c_smbus_write_byte_data(client, CMD_BYTE|APDS9130_ENABLE_REG, 1);
    if(err) {
        printk("[ProximitySensor_E] %s : i2c_write fail(%d) at (%d)\n", __func__, err, __LINE__);
        return;
    }

	printk("[ProximitySensor] %s : [status:0x%02x][enable:0x%02x]\n", __func__, status, enable);
	if ((status & enable & 0x30) == 0x30) {
		/* both PS and ALS are interrupted - never happened*/

		if ( (status&0x40) != 0x40 ) // no PSAT bit set
			apds9130_change_ps_threshold(client);
		else {
			if (data->ps_detection == 1) {
				apds9130_change_ps_threshold(client);
			}
			else {
				printk("* Triggered by background ambient noise\n");
			}
		}

		err = apds9130_set_command(client, 2);	/* 2 = CMD_CLR_PS_ALS_INT */
	}
	else if ((status & enable & 0x20) == 0x20) {
		/* only PS is interrupted */
		
		if ( (status&0x40) != 0x40 ) // no PSAT bit set
			apds9130_change_ps_threshold(client);	// far-to-near
		else {
			if (data->ps_detection == 1) {
				apds9130_change_ps_threshold(client); // near-to-far
			}
			else {
				printk("* Triggered by background ambient noise\n");
			}
		}

		err = apds9130_set_command(client, 0);	/* 0 = CMD_CLR_PS_INT */
	}
	else if ((status & enable & 0x10) == 0x10) {
		/* only ALS is interrupted - will never happened*/	

		err = apds9130_set_command(client, 1);	/* 1 = CMD_CLR_ALS_INT */
	}

    if(err) {
        printk("[ProximitySensor_E] %s : i2c_write fail(%d) at (%d)\n", __func__, err, __LINE__);
        return;
    }

	err = i2c_smbus_write_byte_data(client, CMD_BYTE|APDS9130_ENABLE_REG, data->enable);
    if(err) {
        printk("[ProximitySensor_E] %s : i2c_write fail(%d) at (%d)\n", __func__, err, __LINE__);
        return;
    }
}