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; }
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; }
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; }
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; }
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; }