示例#1
0
void apds_9190_proximity_handler(struct apds9190_data *data) 	
{
		int pdata = i2c_smbus_read_word_data(apds_9190_i2c_client, CMD_WORD|APDS9190_PDATAL_REG);		
				
		if((pdata > data->pilt) && (pdata >= data->piht)){
				apds9190_set_enable(apds_9190_i2c_client,0);
				data->isNear = 0;
				apds9190_set_piht(apds_9190_i2c_client, 1023);
#ifdef APDS9190_TUNE
				apds9190_set_pilt(apds_9190_i2c_client, g_pilt);
#else
				apds9190_set_pilt(apds_9190_i2c_client, apds_proxi_low_threshold);
#endif
				printk(KERN_INFO "%s, piht : %d\n",__func__, data->piht);
				printk(KERN_INFO "%s, pilt : %d\n",__func__, data->pilt);
				printk(KERN_INFO "%s, reg pdata : %d \n",__func__, pdata);
				
		}
		else if((pdata < data->piht) && (pdata <= data->pilt)) {
				apds9190_set_enable(apds_9190_i2c_client,0);		
				data->isNear = 1;

				apds9190_set_pilt(apds_9190_i2c_client, 0);
#ifdef APDS9190_TUNE
				apds9190_set_piht(apds_9190_i2c_client, g_piht);
#else	
				apds9190_set_piht(apds_9190_i2c_client, apds_proxi_high_threshold);
#endif
				printk(KERN_INFO "%s, piht : %d\n",__func__, data->piht);
				printk(KERN_INFO "%s, pilt : %d\n",__func__, data->pilt);				
				printk(KERN_INFO "%s, reg pdata : %d \n",__func__, pdata);

		}

		if(data->isNear != data->last_isNear){
				apds9190_event_report(data->isNear);
				data->last_isNear = data->isNear;
		}

}
示例#2
0
static ssize_t apds9190_store_interrupt(struct device *dev,
				struct device_attribute *attr, const char *buf, size_t count)
{
		// this value should be same with the value in sensors.cpp
#define STORE_INTERUPT_SELECT_PROXIMITY		0x02


		struct i2c_client *client = to_i2c_client(dev);
		struct apds9190_data *data = i2c_get_clientdata(client);
		unsigned long rdata = simple_strtoul(buf, NULL, 10);	
		int enable = (int)rdata;
		int ret;

		DEBUG_MSG("apds9190_store_interrupt = [%d] apds_9190_initlizatied [%d] \n",rdata, apds_9190_initlizatied);

		if(!apds_9190_initlizatied){
				apds_9190_initialize();
				apds_9190_initlizatied = 1;		
		}

		if(enable & STORE_INTERUPT_SELECT_PROXIMITY)
		{	
				if(enable & 0x01) // enable
				{
						data->enable |= (APDS9190_ENABLE_PIEN|APDS9190_ENABLE_PEN|APDS9190_ENABLE_PON); 	
				}
				else		//disable
				{
						data->enable &= ~(APDS9190_ENABLE_PIEN|APDS9190_ENABLE_PEN); 	
				}
		}

		if(data->enable == 1)
		{
				data->enable = 0;
		}

		ret = apds9190_set_enable(client, data->enable);

		enable_status = data->enable;


		DEBUG_MSG("apds9190_store_interrupt enable_status = [%x] data->enable [%x] \n",enable_status, data->enable);

		if (ret < 0)
				return ret;

		return count;
}
示例#3
0
static int apds9190_suspend(struct i2c_client *client, pm_message_t mesg)
{
		struct apds9190_data *data = i2c_get_clientdata(apds_9190_i2c_client);	
		struct proximity_platform_data* pdata = NULL;
		int enable;
		int err;

		printk("apds9190_suspend [%d], proximity_wq=%d\n", data->enable, proximity_wq);

		if(!data->sw_mode)
				return 0;

		pdata = data->client->dev.platform_data;

		if(NULL == pdata){
				printk(KERN_INFO "Platform data is NULL\n");
				return -1;
		}

		apds9190_set_enable(client, 0);
		apds9190_set_command(apds_9190_i2c_client, 2);
		
		cancel_work_sync(&data->dwork);
		flush_work(&data->dwork);
		flush_workqueue(proximity_wq);

		enable_status = enable;
		data->sw_mode = PROX_STAT_SHUTDOWN;
        disable_irq(data->irq);
		err = pdata->power(0);
		if(err < 0) {
			printk(KERN_INFO "%s, Proximity Power Off Fail in susped\n",__func__);
			return err;
		}
			
		set_irq_wake(data->irq, 0);
		if(NULL != proximity_wq){
			destroy_workqueue(proximity_wq);
			printk(KERN_INFO "%s, Destroy workqueue\n",__func__);
			proximity_wq = NULL;
		}
		return 0;
}
示例#4
0
static int apds9190_init_client(struct i2c_client *client)
{
		struct apds9190_data *data = i2c_get_clientdata(apds_9190_i2c_client);
		int err;

		apds9190_set_enable(apds_9190_i2c_client, 0);

		mutex_lock(&data->update_lock);
		err = i2c_smbus_read_byte_data(apds_9190_i2c_client, APDS9190_ENABLE_REG);
		mutex_unlock(&data->update_lock);

		if (err != 0)
				return -ENODEV;

		DEBUG_MSG("apds9190_init_client\n");

		data->enable = 0;

		return 0;
}
示例#5
0
static int __devexit apds9190_remove(struct i2c_client *client)
{
		struct apds9190_data *data = i2c_get_clientdata(client);

		DEBUG_MSG("apds9190_remove\n");

		apds9190_set_enable(client, 0);

		set_irq_wake(data->irq, 0);
		free_irq(data->irq, NULL);
		input_unregister_device(data->input_dev);
		input_free_device(data->input_dev);

		kfree(data);		
		/* Power down the device */

		sysfs_remove_group(&client->dev.kobj, &apds9190_attr_group);

		return 0;
}
示例#6
0
文件: apds9190.c 项目: CurieBSP/main
static int apds9190_init(struct td_device *device)
{
	int ret;
	struct sba_device *dev = (struct sba_device *)device;
	struct apds9190_info *ir_dev = (struct apds9190_info *)device->priv;

	pr_debug(LOG_MODULE_DRV, "APDS9190 %d init", device->id);

	/* Create a taken semaphore for sba transfers */
	if ((ir_dev->i2c_sync_sem = semaphore_create(0)) == NULL) {
		return -1;
	}
	/* Init sba_request struct */
	ir_dev->req.addr.slave_addr = dev->addr.slave_addr;
	ir_dev->req.request_type = SBA_TX;
	ir_dev->irq_req.addr.slave_addr = dev->addr.slave_addr;
	ir_dev->irq_req.request_type = SBA_TX;
	ir_dev->irq_req.tx_buff = ir_dev->irq_tx_buff;
	ir_dev->irq_req.rx_len = 0;
	ir_dev->irq_req.priv_data = dev;

	/* Stop device */
	ret = apds9190_set_enable(device, ENABLE_PON);

	if (ret != 0) {
		pr_error(LOG_MODULE_DRV, "apds9190 %d probe %d\n", device->id,
			 ret);
		return ret;
	}

	/* Default state is detached */
	ir_dev->prox = false;

	/* Enable comparator interrupt if available */
	if (ir_dev->comp_pin < 0) {
		/* No comparator configured, use polling mode */
		apds9190_update_config(device);
		goto apds_polling_mode;
	}

	ir_dev->comparator_device =
		(struct td_device *)&pf_device_soc_comparator;

	pr_info(LOG_MODULE_DRV, "apds: use interrupt mode");
	apds9190_update_config(device);
	apds9190_set_threshold(device, 0, ir_dev->piht);
	/* Enable apds9190 device in interrupt mode */
	apds9190_set_enable(device, ENABLE_PON |
			    ENABLE_PIEN |
			    ENABLE_WEN |
			    ENABLE_PEN);
	apds9190_clear_irq(device);
	comp_configure(ir_dev->comparator_device,
		       ir_dev->comp_pin, 1, 1, comparator_cb, device);

	return 0;

apds_polling_mode:
	pr_info(LOG_MODULE_DRV, "apds: use polling mode");
	/* Disable interrupt mode on apds device */
	apds9190_set_enable(device, ENABLE_PON |
			    ENABLE_WEN |
			    ENABLE_PEN);
	/* Create / start timer */
	timer_create(apds_timer_cb, (void *)device, 1000, true, true, NULL);

	return 0;
}
示例#7
0
static int apds_9190_initialize(void)
{
		struct apds9190_data *data = i2c_get_clientdata(apds_9190_i2c_client);
		u8 enable;
		int err = 0;
		
		data->pDrive = apds_pdrive;

		enable = APDS9190_ENABLE_PIEN | APDS9190_ENABLE_AIEN | APDS9190_ENABLE_WEN | APDS9190_ENABLE_PEN | 
				APDS9190_ENABLE_AEN | APDS9190_ENABLE_PON;

		err = apds9190_set_enable(apds_9190_i2c_client,enable);
		
		if(err < 0){
			printk(KERN_INFO "%s, enable set Fail\n",__func__);
			goto EXIT;
		}

		err = apds9190_set_wtime(apds_9190_i2c_client, WTIME);
		if(err < 0){
			printk(KERN_INFO "%s, wtime set Faile\n",__func__);
			goto EXIT;
		}

		err = apds9190_set_ptime(apds_9190_i2c_client, PTIME);
		if(err < 0){
			printk(KERN_INFO "%s, ptime set Fail\n",__func__);
			goto EXIT;
		}
#ifdef STRONG_LIGHT
		err =  apds9190_set_atime(apds_9190_i2c_client, ATIME);
		if(err < 0){
			printk(KERN_INFO "%s, atime set Fail\n",__func__);
			goto EXIT;
		}	
#endif		
		err = apds9190_set_pers(apds_9190_i2c_client, 0x22); //Interrupt persistence
		if(err < 0){
			printk(KERN_INFO "%s, pers set Fail\n",__func__);
			goto EXIT;
		}

		err = apds9190_set_config(apds_9190_i2c_client, 0x00); // Wait long timer <- no needs so set 0
		if(err < 0){
			printk(KERN_INFO "%s, config set Fail\n",__func__);
			goto EXIT;
		}

		err = apds9190_set_ppcount(apds_9190_i2c_client, apds_ppcount); // Pulse count for proximity
		if(err < 0){
			printk(KERN_INFO "%s, ppcount set Fail\n",__func__);
			goto EXIT;
		}

		err = apds9190_set_control(apds_9190_i2c_client, data->pDrive| PDIODE | PGAIN | AGAIN);
		if(err < 0){
			printk(KERN_INFO "%s, control set Fail\n",__func__);
			goto EXIT;
		}

		err = apds9190_set_pilt(apds_9190_i2c_client, 0); // init threshold for proximity
		if(err < 0){
			printk(KERN_INFO "%s, pilt set Fail\n",__func__);
			goto EXIT;
		}
		
		err = apds9190_set_piht(apds_9190_i2c_client, apds_proxi_high_threshold);
		if(err < 0){
			printk(KERN_INFO "%s, piht set Fail\n",__func__);
			goto EXIT;
		}
#ifdef STRONG_LIGHT
		err = apds9190_set_aiht(apds_9190_i2c_client, (75*(1024*(256-data->atime)))/100);
		if(err < 0){
			printk(KERN_INFO "%s, aiht set Fail\n",__func__);
			goto EXIT;
		}
		
		err = apds9190_set_ailt(apds_9190_i2c_client, 0);
		if(err < 0){
			printk(KERN_INFO "%s, ailt set Fail\n",__func__);
			goto EXIT;
		}		
#endif		
		enable_status = enable;

		data->pilt = 0;
		data->piht = apds_proxi_high_threshold;

#ifdef APDS9190_TUNE		
		g_pilt = apds_proxi_low_threshold;
		g_piht = apds_proxi_high_threshold;
#endif		
		return 0;
EXIT:
	return err;
}
示例#8
0
void apds_9190_irq_work_func(struct work_struct *work) 	
{
		struct apds9190_data *data = 
				container_of(work, struct apds9190_data, dwork);
		struct proximity_platform_data		*pdev = NULL;	
#ifdef STRONG_LIGHT		
		int status, pdata, cdata;
#else
		int status, pdata;
#endif
		int org_enable = data->enable;
			

		pdev = data->client->dev.platform_data;

		if(pdev->methods){
				
				status = i2c_smbus_read_byte_data(apds_9190_i2c_client, CMD_BYTE|APDS9190_STATUS_REG);
#ifdef STRONG_LIGHT

				if((status & APDS9190_STATUS_PINT_AINT) == 0x30) 
				{
					disable_irq(data->irq);

					cdata = i2c_smbus_read_word_data(apds_9190_i2c_client, CMD_WORD|APDS9190_CDATAL_REG);
				
					printk(KERN_INFO "%s, [APDS9190_STATUS_PINT_AINT] status : %d,   cdata : %d, isNear : %d\n",__func__, status, cdata, data->isNear);		

					if((data->isNear == 0) && (cdata >= (75*(1024*(256-data->atime)))/100) )
					{
						pdata = i2c_smbus_read_word_data(apds_9190_i2c_client, CMD_WORD|APDS9190_PDATAL_REG);													
						printk(KERN_INFO "%s, [APDS9190_STATUS_PINT_AINT] cdata : %d, pdata : %d\n", __func__, cdata, pdata);

						printk(KERN_INFO "%s, [APDS9190_STATUS_PINT_AINT] status change Near to Far while Near status but couldn't recognize Far\n", __func__);
						printk(KERN_INFO "%s, [APDS9190_STATUS_PINT_AINT] Force status to change Far\n",__func__);
						data->isNear = 1;
						data->last_isNear = 0;
						apds9190_set_pilt(apds_9190_i2c_client, 0);
#ifdef APDS9190_TUNE
						apds9190_set_piht(apds_9190_i2c_client,g_piht);
#else
						apds9190_set_piht(apds_9190_i2c_client,apds_proxi_high_threshold);
#endif
						if(data->isNear != data->last_isNear)
						{
							apds9190_event_report(data->isNear);
							data->last_isNear = data->isNear;
						}
					}
					else if((data->isNear == 1) && (cdata >= (75*(1024*(256-data->atime)))/100) )
					{
						pdata = i2c_smbus_read_word_data(apds_9190_i2c_client, CMD_WORD|APDS9190_PDATAL_REG);													
						printk(KERN_INFO "%s, [APDS9190_STATUS_PINT_AINT] cdata : %d, pdata : %d\n", __func__, cdata, pdata);												
					}
					else if(cdata < (75*(1024*(256-data->atime)))/100) 
					{
						apds_9190_proximity_handler(data);
					}		
					else // Far state
					{
						pdata = i2c_smbus_read_word_data(apds_9190_i2c_client, CMD_WORD|APDS9190_PDATAL_REG);							
						printk(KERN_ERR "%s, [APDS9190_STATUS_PINT_AINT] Triggered by background ambient noise pdata : %d isNear : %d\n", __func__, pdata, data->isNear);		
					}


					apds9190_set_command(apds_9190_i2c_client, 2);

					data->enable = org_enable;

					apds9190_set_control(apds_9190_i2c_client, (data->pDrive | PDIODE | PGAIN | AGAIN));
					apds9190_set_enable(apds_9190_i2c_client,org_enable);

					enable_irq(data->irq);
				}
				else if((status & APDS9190_STATUS_PINT)  == 0x20) 
				{	
					disable_irq(data->irq);

					cdata = i2c_smbus_read_word_data(apds_9190_i2c_client, CMD_WORD|APDS9190_CDATAL_REG);
					printk(KERN_INFO "%s, [APDS9190_STATUS_PINT] status : %d,   cdata : %d, isNear : %d\n",__func__, status, cdata, data->isNear);		

					if((data->isNear == 0) && (cdata >= (75*(1024*(256-data->atime)))/100) ) // Near state light 75% 
					{
						pdata = i2c_smbus_read_word_data(apds_9190_i2c_client, CMD_WORD|APDS9190_PDATAL_REG);
						printk(KERN_INFO "%s, [APDS9190_STATUS_PINT] cdata : %d, pdata : %d\n", __func__, cdata, pdata);

						printk(KERN_INFO "%s, [APDS9190_STATUS_PINT] status change Near to Far while Near status but couldn't recognize Far\n", __func__);
						printk(KERN_INFO "%s, [APDS9190_STATUS_PINT] Force status to change Far\n",__func__);
						data->isNear = 1;
						data->last_isNear = 0;
						apds9190_set_pilt(apds_9190_i2c_client, 0);
#ifdef APDS9190_TUNE
						apds9190_set_piht(apds_9190_i2c_client,g_piht);
#else
						apds9190_set_piht(apds_9190_i2c_client,apds_proxi_high_threshold);
#endif
						if(data->isNear != data->last_isNear)
						{
							apds9190_event_report(data->isNear);
							data->last_isNear = data->isNear;
						}
					}
					else if((data->isNear == 1) && (cdata >= (75*(1024*(256-data->atime)))/100) )
					{
						pdata = i2c_smbus_read_word_data(apds_9190_i2c_client, CMD_WORD|APDS9190_PDATAL_REG);													
						printk(KERN_INFO "%s, [APDS9190_STATUS_PINT_AINT] cdata : %d, pdata : %d\n", __func__, cdata, pdata);												
					}
					else if(cdata < (75 * (1024 * (256 - data->atime))) / 100)
					{
						apds_9190_proximity_handler(data);
					}
					else // Far state
					{
						printk(KERN_ERR "%s, [APDS9190_STATUS_PINT] Triggered by background ambient noise pdata : %d isNear : %d\n", __func__, pdata, data->isNear);		
					}
					
					apds9190_set_command(apds_9190_i2c_client, 0);

					data->enable = org_enable;

					apds9190_set_control(apds_9190_i2c_client, (data->pDrive | PDIODE | PGAIN | AGAIN));
					apds9190_set_enable(apds_9190_i2c_client,org_enable);
					

					enable_irq(data->irq);
				}
				else if((status & APDS9190_STATUS_AINT) == 0x10) 
				{
					apds9190_set_command(apds_9190_i2c_client, 1);
				}
#else
				if((status & APDS9190_STATUS_PINT)  == 0x20){

					disable_irq(data->irq);
					
					apds_9190_proximity_handler(data);
					
					apds9190_set_command(apds_9190_i2c_client, 0);

					data->enable = org_enable;

					apds9190_set_control(apds_9190_i2c_client, (data->pDrive | PDIODE | PGAIN | AGAIN));
					apds9190_set_enable(apds_9190_i2c_client,org_enable);

					printk(KERN_INFO "%s, irq num : %d\n",__func__,data->irq);
					printk(KERN_INFO "%s, enable irq\n",__func__);

					enable_irq(data->irq);
				}
#endif
		}	
		else{
				mutex_lock(&data->update_lock);

				pdata = i2c_smbus_read_word_data(data->client, CMD_WORD|APDS9190_PDATAL_REG);

				i2c_smbus_write_byte(data->client, CMD_CLR_PS_INT);
				mutex_unlock(&data->update_lock);


				if(pdata > PROX_HIGH_TH) // near intr
						data->isNear = 0; 
				else
						data->isNear = 1; // far intr,  pdata<= PROX_INT_LOW_TH


				if(data->isNear != data->last_isNear)
						apds9190_event_report(data->isNear);

				data->enable = org_enable;

				apds9190_set_control(apds_9190_i2c_client, (data->pDrive | PDIODE | PGAIN | AGAIN));
				apds9190_set_enable(apds_9190_i2c_client,org_enable);

		}

}