Example #1
0
static int apds990x_init_client(struct i2c_client *client)
{
    struct apds990x_data *data = i2c_get_clientdata(client);
    int err;
    int id;

    data->enable_ps_sensor = 1;
    data->enable_als_sensor = 1;

    err = apds990x_set_enable(client, 0);

    if (err < 0)
        return err;
    
    id = i2c_smbus_read_byte_data(client, CMD_BYTE|APDS990x_ID_REG);
    if (id == 0x20) {
        APDS_DEBUG_LOG("APDS-9901\n");
    }
    else if (id == 0x29) {
        APDS_DEBUG_LOG("APDS-990x\n");
    }
    else {
        APDS_DEBUG_LOG("Neither APDS-9901 nor APDS-9901\n");
        return -EIO;
    }

    apds990x_set_atime(client, 0xC0);
    apds990x_set_ptime(client, 0xFF);
    apds990x_set_wtime(client, 0xE8);

    apds990x_set_ppcount(client, 0x04);
    apds990x_set_config(client, 0);
    apds990x_set_control(client, 0x20);

    apds990x_set_pilt(client, 0);
    apds990x_set_piht(client, guc_nv_proximity_sensor_near[0]);

    data->ps_threshold = guc_nv_proximity_sensor_near[0];
    data->ps_hysteresis_threshold = guc_nv_proximity_sensor_far[0];

    apds990x_set_ailt(client, 0);
    apds990x_set_aiht(client, 0xFFFF);

    apds990x_set_pers(client, 0x22);

    data->enable_ps_sensor = 0;
    data->enable_als_sensor = 0;
    err = apds990x_set_enable(client, 0);


    return 0;
}
Example #2
0
static int __devexit apds990x_remove(struct i2c_client *client)
{
    struct apds990x_data *data = i2c_get_clientdata(client);
    
    input_unregister_device(data->input_dev_als);
    input_unregister_device(data->input_dev_ps);
    
    input_free_device(data->input_dev_als);
    input_free_device(data->input_dev_ps);

    wake_lock_destroy( &apds_wake_lock );

    free_irq(data->ps_irq, client);

    sysfs_remove_group(&client->dev.kobj, &apds990x_attr_group);
    misc_deregister(&apds990x_device);

    data->enable_ps_sensor = 0;
    data->enable_als_sensor = 0;
    
    apds990x_set_enable(client, 0);

    kfree(data);

    return 0;
}
Example #3
0
static int apds990x_init_client(struct i2c_client *client)
{
	struct apds990x_data *data = i2c_get_clientdata(client);
	int err;
	int id;

	err = apds990x_set_enable(client, 0);

	if (err < 0)
		return err;
	
	id = i2c_smbus_read_byte_data(client, CMD_BYTE|APDS990x_ID_REG);
	if (id == 0x20) {
		printk("APDS-9901\n");
	}
	else if (id == 0x29) {
		printk("APDS-990x\n");
	}
	else {
		printk("Neither APDS-9901 nor APDS-9901\n");
		return -EIO;
	}

	apds990x_set_atime(client, 0xDB);	// 100.64ms ALS integration time
	apds990x_set_ptime(client, 0xFF);	// 2.72ms Prox integration time
	apds990x_set_wtime(client, 0xFF);	// 2.72ms Wait time

	apds990x_set_ppcount(client, 0x08);	// 8-Pulse for proximity
	apds990x_set_config(client, 0);		// no long wait
	apds990x_set_control(client, 0x60);	// 100mA, IR-diode, 1X PGAIN, 1X AGAIN

	apds990x_set_pilt(client, 0);		// init threshold for proximity
	apds990x_set_piht(client, APDS990x_PS_DETECTION_THRESHOLD);

	data->ps_threshold = APDS990x_PS_DETECTION_THRESHOLD;
	data->ps_hysteresis_threshold = APDS990x_PS_HSYTERESIS_THRESHOLD;

	apds990x_set_ailt(client, 0);		// init threshold for als
	apds990x_set_aiht(client, 0xFFFF);

	apds990x_set_pers(client, 0x22);	// 2 consecutive Interrupt persistence

	// sensor is in disabled mode but all the configurations are preset

	return 0;
}
Example #4
0
static int __devexit apds990x_remove(struct i2c_client *client)
{
	struct apds990x_data *data = i2c_get_clientdata(client);
	
	wake_lock_destroy(&apds990x_wake_lock);
	input_unregister_device(data->input_dev_als);
	input_unregister_device(data->input_dev_ps);
	
	input_free_device(data->input_dev_als);
	input_free_device(data->input_dev_ps);

	free_irq(client->irq, client);

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

	/* Power down the device */
	apds990x_set_enable(client, 0);

	kfree(data);

	return 0;
}
Example #5
0
static ssize_t apds990x_store_enable_als_sensor(struct device *dev,
				struct device_attribute *attr, const char *buf, size_t count)
{
	struct i2c_client *client = to_i2c_client(dev);
	struct apds990x_data *data = i2c_get_clientdata(client);
	unsigned long val = simple_strtoul(buf, NULL, 10);
 	unsigned long flags;
	
	printk("%s: enable als sensor ( %ld)\n", __func__, val);
	
	if ((val != 0) && (val != 1))
	{
		printk("%s: enable als sensor=%ld\n", __func__, val);
		return count;
	}
	
	if(val == 1) {
		//turn on light  sensor
		if (data->enable_als_sensor==0) {

			data->enable_als_sensor = 1;
		
			apds990x_set_enable(client,0); /* Power Off */
		
			apds990x_set_atime(client, data->als_atime);  /* 100.64ms */
		
			apds990x_set_ailt( client, 0);
			apds990x_set_aiht( client, 0xffff);
		
			apds990x_set_control(client, data->control); /* 100mA, IR-diode, 1X PGAIN, 1X AGAIN */
			apds990x_set_pers(client, 0x33); /* 3 persistence */
		
			if (data->enable_ps_sensor) {
				apds990x_set_ptime(client, 0xff); /* 2.72ms */
			
				apds990x_set_ppcount(client, 8); /* 8-pulse */
				apds990x_set_enable(client, 0x27);	 /* if prox sensor was activated previously */
			}
			else {
				apds990x_set_enable(client, 0x3);	 /* only enable light sensor */
			}
		
			spin_lock_irqsave(&data->update_lock.wait_lock, flags); 
		
			/*
			 * 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->als_dwork);
			schedule_delayed_work(&data->als_dwork, msecs_to_jiffies(data->als_poll_delay));
		
			spin_unlock_irqrestore(&data->update_lock.wait_lock, flags);
		}
	}
	else {
		//turn off light sensor
		// what if the p sensor is active?
		data->enable_als_sensor = 0;
		if (data->enable_ps_sensor) {
			apds990x_set_enable(client,0); /* Power Off */
			apds990x_set_atime(client, 0xf6);  /* 27.2ms */
			apds990x_set_ptime(client, 0xff); /* 2.72ms */
			apds990x_set_ppcount(client, 8); /* 8-pulse */
			apds990x_set_control(client, data->control); /* 100mA, IR-diode, 1X PGAIN, 1X AGAIN */
			
			//apds990x_set_piht(client, 0);
			//apds990x_set_piht(client, APDS990x_PS_DETECTION_THRESHOLD);
			
			apds990x_set_ailt( client, 0);
			apds990x_set_aiht( client, 0xffff);
			
			apds990x_set_pers(client, 0x33); /* 3 persistence */
			apds990x_set_enable(client, 0x27);	 /* only enable prox sensor with interrupt */			
		}
		else {
			apds990x_set_enable(client, 0);
		}
		
		
		spin_lock_irqsave(&data->update_lock.wait_lock, flags); 
		
		/*
		 * 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->als_dwork);
		
		spin_unlock_irqrestore(&data->update_lock.wait_lock, flags); 
	}
	
	return count;
}
Example #6
0
static ssize_t apds990x_store_enable_ps_sensor(struct device *dev,
				struct device_attribute *attr, const char *buf, size_t count)
{
	struct i2c_client *client = to_i2c_client(dev);
	struct apds990x_data *data = i2c_get_clientdata(client);
	unsigned long val = simple_strtoul(buf, NULL, 10);
 	unsigned long flags;
	
	printk("%s: enable ps senosr ( %ld)\n", __func__, val);
	
	if ((val != 0) && (val != 1)) {
		printk("%s:store unvalid value=%ld\n", __func__, val);
		return count;
	}
	
	if(val == 1) {
		//turn on p sensor
		if (data->enable_ps_sensor==0) {

			data->enable_ps_sensor= 1;
		
			apds990x_set_enable(client,0); /* Power Off */
			apds990x_set_atime(client, 0xf6); /* 27.2ms */
			apds990x_set_ptime(client, 0xff); /* 2.72ms */
		
			apds990x_set_ppcount(client, 8); /* 8-pulse */
			apds990x_set_control(client, data->control); /* 100mA, IR-diode, 1X PGAIN, 1X AGAIN */
		
			apds990x_set_pilt(client, 0);		// init threshold for proximity
			apds990x_set_piht(client, APDS990x_PS_DETECTION_THRESHOLD);

			data->ps_threshold = APDS990x_PS_DETECTION_THRESHOLD;
			data->ps_hysteresis_threshold = APDS990x_PS_HSYTERESIS_THRESHOLD;
		
			apds990x_set_ailt( client, 0);
			apds990x_set_aiht( client, 0xffff);
		
			apds990x_set_pers(client, 0x33); /* 3 persistence */
		
			if (data->enable_als_sensor==0) {

				/* we need this polling timer routine for sunlight canellation */
				spin_lock_irqsave(&data->update_lock.wait_lock, flags); 
			
				/*
				 * 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->als_dwork);
				schedule_delayed_work(&data->als_dwork, msecs_to_jiffies(data->als_poll_delay));	// 100ms
			
				spin_unlock_irqrestore(&data->update_lock.wait_lock, flags);	
			}

			apds990x_set_enable(client, 0x27);	 /* only enable PS interrupt */
		}
	} 
	else {
		//turn off p sensor - kk 25 Apr 2011 we can't turn off the entire sensor, the light sensor may be needed by HAL
		data->enable_ps_sensor = 0;
		if (data->enable_als_sensor) {
			
			// reconfigute light sensor setting			
			apds990x_set_enable(client,0); /* Power Off */
			
			apds990x_set_atime(client, data->als_atime);  /* previous als poll delay */
			
			apds990x_set_ailt( client, 0);
			apds990x_set_aiht( client, 0xffff);
			
			apds990x_set_control(client, data->control); /* 100mA, IR-diode, 1X PGAIN, 1X AGAIN */
			apds990x_set_pers(client, 0x33); /* 3 persistence */
			
			apds990x_set_enable(client, 0x3);	 /* only enable light sensor */
			
			spin_lock_irqsave(&data->update_lock.wait_lock, flags); 
			
			/*
			 * 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->als_dwork);
			schedule_delayed_work(&data->als_dwork, msecs_to_jiffies(data->als_poll_delay));	// 100ms
			
			spin_unlock_irqrestore(&data->update_lock.wait_lock, flags);	
			
		}
		else {
			apds990x_set_enable(client, 0);

			spin_lock_irqsave(&data->update_lock.wait_lock, flags); 
			
			/*
			 * 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->als_dwork);
		
			spin_unlock_irqrestore(&data->update_lock.wait_lock, flags); 
		}
	}
	
	
	return count;
}
Example #7
0
static ssize_t apds990x_store_enable_als_sensor(struct device *dev,
                struct device_attribute *attr, const char *buf, size_t count)
{
    struct i2c_client *client = to_i2c_client(dev);
    struct apds990x_data *data = i2c_get_clientdata(client);
    unsigned long val = simple_strtoul(buf, NULL, 10);
    unsigned long flags;
    
    APDS_DEBUG_LOG("%s: enable als sensor ( %ld)\n", __func__, val);
    
    if ((val != 0) && (val != 1))
    {
        APDS_DEBUG_LOG("%s: enable als sensor=%ld\n", __func__, val);
        return count;
    }
    
    if(val == 1) {
        if (data->enable_als_sensor<=0) {

            data->enable_als_sensor = 1;
        
            if (data->enable_ps_sensor<=0) {
                apds990x_set_enable(client,0);
                apds990x_set_atime(client, 0xC0);
                apds990x_set_ptime(client, 0xff);
                apds990x_set_wtime(client, 0xE8);
                apds990x_set_ppcount(client, 0x04);
                apds990x_set_control(client, 0x20);
                apds990x_set_pers(client, 0x22);
                apds990x_set_config(client, 0x00);
                apds990x_set_enable(client, 0x0B);
            }
        
            spin_lock_irqsave(&data->update_lock.wait_lock, flags); 
        
            __cancel_delayed_work(&data->als_dwork);
            schedule_delayed_work(&data->als_dwork, msecs_to_jiffies(data->als_poll_delay));
        
            spin_unlock_irqrestore(&data->update_lock.wait_lock, flags);
        }
        else
        {
            data->enable_als_sensor++;
        }
    }
    else {
        data->enable_als_sensor--;
        if( data->enable_als_sensor > 0)
        {
            ;
        }
        else {
            if (data->enable_ps_sensor<=0) {
                apds990x_set_enable(client, 0);
            }
        
            spin_lock_irqsave(&data->update_lock.wait_lock, flags); 
            
            __cancel_delayed_work(&data->als_dwork);
            
            spin_unlock_irqrestore(&data->update_lock.wait_lock, flags); 
            
            data->als_polling_cnt_reset |= ALS_POLLING_CNT_RESET_DISABLE;
        }
    }
    
    return count;
}
Example #8
0
static ssize_t apds990x_store_enable_ps_sensor(struct device *dev,
                struct device_attribute *attr, const char *buf, size_t count)
{
    struct i2c_client *client = to_i2c_client(dev);
    struct apds990x_data *data = i2c_get_clientdata(client);
    unsigned long val = simple_strtoul(buf, NULL, 10);
    unsigned long flags;
    
    APDS_DEBUG_LOG("%s: enable ps senosr ( %ld)\n", __func__, val);
    
    if ((val != 0) && (val != 1)) {
        APDS_DEBUG_LOG("%s:store unvalid value=%ld\n", __func__, val);
        return count;
    }
    
    if(val == 1) {
        if (data->enable_ps_sensor<=0) {

            data->enable_ps_sensor=1;
        
            if (data->enable_als_sensor<=0) {
                apds990x_set_enable(client,0);
                apds990x_set_atime(client, 0xC0);
                apds990x_set_ptime(client, 0xff);
                apds990x_set_ppcount(client, 0x04);
                apds990x_set_pers(client, 0x22);
                apds990x_set_config(client, 0x00);
            }

            apds990x_set_wtime(client, 0xE5);
            apds990x_set_ailt(client, guc_nv_photo_sensor_dark[0]);
            apds990x_set_aiht(client, 0xffff);
            apds990x_set_pilt(client, 0);
            apds990x_set_piht(client, guc_nv_proximity_sensor_near[0]);
            if( data->als_gain == APDS990X_ALS_GAIN_1X )
            {
                apds990x_set_control(client, 0x20);
            }
            else
            {
                apds990x_set_control(client, 0x20);
                msleep(250);
            }

            data->ps_threshold = guc_nv_proximity_sensor_near[0];
            data->ps_hysteresis_threshold = guc_nv_proximity_sensor_far[0];

            data->ps_detection = 0;

            apds990x_set_enable(client, 0x2F);
            apds990x_enable_ps_irq(data);
        } else
        {
            data->enable_ps_sensor++;
        }
    } 
    else {
        data->enable_ps_sensor--;
        
        if (data->enable_ps_sensor>0) {
            ;
        } else if(data->enable_als_sensor) {
            
            apds990x_disable_ps_irq(data);
            apds990x_set_enable(client, 0x0A);
            i2c_smbus_write_byte(client, CMD_SPECIAL|0x07);
            apds990x_set_wtime(client, 0xE8);
            apds990x_set_enable(client, 0xB);
            
            if( data->ps_detection != 0 )
            {
                data->ps_detection = 0;
                input_report_abs(data->input_dev_ps, ABS_DISTANCE, 0);
                input_sync(data->input_dev_ps);
            }

            spin_lock_irqsave(&data->update_lock.wait_lock, flags); 
            
            __cancel_delayed_work(&data->als_dwork);
            schedule_delayed_work(&data->als_dwork, msecs_to_jiffies(data->als_poll_delay));
            
            spin_unlock_irqrestore(&data->update_lock.wait_lock, flags);    
            
        }
        else {
            apds990x_disable_ps_irq(data);
            i2c_smbus_write_byte_data(client, CMD_BYTE|APDS990x_ENABLE_REG, 0x08);
            i2c_smbus_write_byte(client, CMD_SPECIAL|0x07);
            apds990x_set_wtime(client, 0xE8);
            apds990x_set_enable(client, 0);

            if( data->ps_detection != 0 )
            {
                data->ps_detection = 0;
                input_report_abs(data->input_dev_ps, ABS_DISTANCE, 0);
                input_sync(data->input_dev_ps);
            }
        }
    }
    
    
    return count;
}