#include <linux/bitfield.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/err.h>
#include <linux/delay.h>
#include <linux/pm_runtime.h>
#include <linux/interrupt.h>
#include <linux/units.h>
#include <linux/iio/buffer.h>
#include <linux/iio/events.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/trigger.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
#define VCNL4000_DRV_NAME …
#define VCNL4000_PROD_ID …
#define VCNL4010_PROD_ID …
#define VCNL4040_PROD_ID …
#define VCNL4200_PROD_ID …
#define VCNL4000_COMMAND …
#define VCNL4000_PROD_REV …
#define VCNL4010_PROX_RATE …
#define VCNL4000_LED_CURRENT …
#define VCNL4000_AL_PARAM …
#define VCNL4010_ALS_PARAM …
#define VCNL4000_AL_RESULT_HI …
#define VCNL4000_AL_RESULT_LO …
#define VCNL4000_PS_RESULT_HI …
#define VCNL4000_PS_RESULT_LO …
#define VCNL4000_PS_MEAS_FREQ …
#define VCNL4010_INT_CTRL …
#define VCNL4000_PS_MOD_ADJ …
#define VCNL4010_LOW_THR_HI …
#define VCNL4010_LOW_THR_LO …
#define VCNL4010_HIGH_THR_HI …
#define VCNL4010_HIGH_THR_LO …
#define VCNL4010_ISR …
#define VCNL4200_AL_CONF …
#define VCNL4200_PS_CONF1 …
#define VCNL4200_PS_CONF3 …
#define VCNL4040_PS_THDL_LM …
#define VCNL4040_PS_THDH_LM …
#define VCNL4040_ALS_THDL_LM …
#define VCNL4040_ALS_THDH_LM …
#define VCNL4200_PS_DATA …
#define VCNL4200_AL_DATA …
#define VCNL4040_INT_FLAGS …
#define VCNL4200_INT_FLAGS …
#define VCNL4200_DEV_ID …
#define VCNL4040_DEV_ID …
#define VCNL4000_AL_RDY …
#define VCNL4000_PS_RDY …
#define VCNL4000_AL_OD …
#define VCNL4000_PS_OD …
#define VCNL4000_ALS_EN …
#define VCNL4000_PROX_EN …
#define VCNL4000_SELF_TIMED_EN …
#define VCNL4040_ALS_CONF_ALS_SHUTDOWN …
#define VCNL4040_ALS_CONF_IT …
#define VCNL4040_ALS_CONF_INT_EN …
#define VCNL4040_ALS_CONF_PERS …
#define VCNL4040_PS_CONF1_PS_SHUTDOWN …
#define VCNL4040_PS_CONF2_PS_IT …
#define VCNL4040_CONF1_PS_PERS …
#define VCNL4040_PS_CONF2_PS_HD …
#define VCNL4040_PS_CONF2_PS_INT …
#define VCNL4040_PS_CONF3_MPS …
#define VCNL4040_PS_MS_LED_I …
#define VCNL4040_PS_IF_AWAY …
#define VCNL4040_PS_IF_CLOSE …
#define VCNL4040_ALS_RISING …
#define VCNL4040_ALS_FALLING …
#define VCNL4010_INT_THR_SEL …
#define VCNL4010_INT_THR_EN …
#define VCNL4010_INT_ALS_EN …
#define VCNL4010_INT_PROX_EN …
#define VCNL4010_INT_THR_HIGH …
#define VCNL4010_INT_THR_LOW …
#define VCNL4010_INT_ALS …
#define VCNL4010_INT_PROXIMITY …
#define VCNL4010_INT_THR …
#define VCNL4010_INT_DRDY …
#define VCNL4040_CONF3_PS_MPS_16BITS …
#define VCNL4040_CONF3_PS_LED_I_16BITS …
#define VCNL4040_CONF3_PS_SAMPLE_16BITS …
static const int vcnl4010_prox_sampling_frequency[][2] = …;
static const int vcnl4040_ps_it_times[][2] = …;
static const int vcnl4200_ps_it_times[][2] = …;
static const int vcnl4040_als_it_times[][2] = …;
static const int vcnl4200_als_it_times[][2] = …;
static const int vcnl4040_ps_calibbias_ua[][2] = …;
static const int vcnl4040_als_persistence[] = …;
static const int vcnl4040_ps_persistence[] = …;
static const int vcnl4040_ps_oversampling_ratio[] = …;
#define VCNL4000_SLEEP_DELAY_MS …
enum vcnl4000_device_ids { … };
struct vcnl4200_channel { … };
struct vcnl4000_data { … };
struct vcnl4000_chip_spec { … };
static const struct i2c_device_id vcnl4000_id[] = …;
MODULE_DEVICE_TABLE(i2c, vcnl4000_id);
static int vcnl4000_set_power_state(struct vcnl4000_data *data, bool on)
{ … }
static int vcnl4000_init(struct vcnl4000_data *data)
{
int ret, prod_id;
ret = i2c_smbus_read_byte_data(data->client, VCNL4000_PROD_REV);
if (ret < 0)
return ret;
prod_id = ret >> 4;
switch (prod_id) {
case VCNL4000_PROD_ID:
if (data->id != VCNL4000)
dev_warn(&data->client->dev,
"wrong device id, use vcnl4000");
break;
case VCNL4010_PROD_ID:
if (data->id != VCNL4010)
dev_warn(&data->client->dev,
"wrong device id, use vcnl4010/4020");
break;
default:
return -ENODEV;
}
data->rev = ret & 0xf;
data->al_scale = 250000;
return data->chip_spec->set_power_state(data, true);
};
static ssize_t vcnl4000_write_als_enable(struct vcnl4000_data *data, bool en)
{ … }
static ssize_t vcnl4000_write_ps_enable(struct vcnl4000_data *data, bool en)
{ … }
static int vcnl4200_set_power_state(struct vcnl4000_data *data, bool on)
{ … }
static int vcnl4200_init(struct vcnl4000_data *data)
{
int ret, id;
u16 regval;
ret = i2c_smbus_read_word_data(data->client, VCNL4200_DEV_ID);
if (ret < 0)
return ret;
id = ret & 0xff;
if (id != VCNL4200_PROD_ID) {
ret = i2c_smbus_read_word_data(data->client, VCNL4040_DEV_ID);
if (ret < 0)
return ret;
id = ret & 0xff;
if (id != VCNL4040_PROD_ID)
return -ENODEV;
}
dev_dbg(&data->client->dev, "device id 0x%x", id);
data->rev = (ret >> 8) & 0xf;
data->ps_int = 0;
data->als_int = 0;
data->vcnl4200_al.reg = VCNL4200_AL_DATA;
data->vcnl4200_ps.reg = VCNL4200_PS_DATA;
switch (id) {
case VCNL4200_PROD_ID:
data->vcnl4200_al.sampling_rate = ktime_set(0, 60000 * 1000);
data->vcnl4200_ps.sampling_rate = ktime_set(0, 5760 * 1000);
break;
case VCNL4040_PROD_ID:
data->vcnl4200_al.sampling_rate = ktime_set(0, 96000 * 1000);
data->vcnl4200_ps.sampling_rate = ktime_set(0, 6000 * 1000);
break;
}
data->al_scale = data->chip_spec->ulux_step;
data->ps_scale = 16;
mutex_init(&data->vcnl4200_al.lock);
mutex_init(&data->vcnl4200_ps.lock);
ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1);
if (ret < 0)
return ret;
regval = ret | VCNL4040_PS_CONF2_PS_HD;
ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF1,
regval);
if (ret < 0)
return ret;
ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF3);
if (ret < 0)
return ret;
regval = ret | VCNL4040_CONF3_PS_SAMPLE_16BITS;
ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF3,
regval);
if (ret < 0)
return ret;
ret = data->chip_spec->set_power_state(data, true);
if (ret < 0)
return ret;
return 0;
};
static int vcnl4000_read_data(struct vcnl4000_data *data, u8 data_reg, int *val)
{ … }
static int vcnl4000_write_data(struct vcnl4000_data *data, u8 data_reg, int val)
{ … }
static int vcnl4000_measure(struct vcnl4000_data *data, u8 req_mask,
u8 rdy_mask, u8 data_reg, int *val)
{ … }
static int vcnl4200_measure(struct vcnl4000_data *data,
struct vcnl4200_channel *chan, int *val)
{ … }
static int vcnl4000_measure_light(struct vcnl4000_data *data, int *val)
{ … }
static int vcnl4200_measure_light(struct vcnl4000_data *data, int *val)
{ … }
static int vcnl4000_measure_proximity(struct vcnl4000_data *data, int *val)
{ … }
static int vcnl4200_measure_proximity(struct vcnl4000_data *data, int *val)
{ … }
static int vcnl4010_read_proxy_samp_freq(struct vcnl4000_data *data, int *val,
int *val2)
{ … }
static bool vcnl4010_is_in_periodic_mode(struct vcnl4000_data *data)
{ … }
static int vcnl4000_set_pm_runtime_state(struct vcnl4000_data *data, bool on)
{ … }
static int vcnl4040_read_als_it(struct vcnl4000_data *data, int *val, int *val2)
{ … }
static ssize_t vcnl4040_write_als_it(struct vcnl4000_data *data, int val)
{ … }
static int vcnl4040_read_ps_it(struct vcnl4000_data *data, int *val, int *val2)
{ … }
static ssize_t vcnl4040_write_ps_it(struct vcnl4000_data *data, int val)
{ … }
static ssize_t vcnl4040_read_als_period(struct vcnl4000_data *data, int *val, int *val2)
{ … }
static ssize_t vcnl4040_write_als_period(struct vcnl4000_data *data, int val, int val2)
{ … }
static ssize_t vcnl4040_read_ps_period(struct vcnl4000_data *data, int *val, int *val2)
{ … }
static ssize_t vcnl4040_write_ps_period(struct vcnl4000_data *data, int val, int val2)
{ … }
static ssize_t vcnl4040_read_ps_oversampling_ratio(struct vcnl4000_data *data, int *val)
{ … }
static ssize_t vcnl4040_write_ps_oversampling_ratio(struct vcnl4000_data *data, int val)
{ … }
static ssize_t vcnl4040_read_ps_calibbias(struct vcnl4000_data *data, int *val, int *val2)
{ … }
static ssize_t vcnl4040_write_ps_calibbias(struct vcnl4000_data *data, int val)
{ … }
static int vcnl4000_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{ … }
static int vcnl4040_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val, int val2, long mask)
{ … }
static int vcnl4040_read_avail(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
const int **vals, int *type, int *length,
long mask)
{ … }
static int vcnl4010_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{ … }
static int vcnl4010_read_avail(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
const int **vals, int *type, int *length,
long mask)
{ … }
static int vcnl4010_write_proxy_samp_freq(struct vcnl4000_data *data, int val,
int val2)
{ … }
static int vcnl4010_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val, int val2, long mask)
{ … }
static int vcnl4010_read_event(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
enum iio_event_info info,
int *val, int *val2)
{ … }
static int vcnl4010_write_event(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
enum iio_event_info info,
int val, int val2)
{ … }
static int vcnl4040_read_event(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
enum iio_event_info info,
int *val, int *val2)
{ … }
static int vcnl4040_write_event(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
enum iio_event_info info,
int val, int val2)
{ … }
static bool vcnl4010_is_thr_enabled(struct vcnl4000_data *data)
{ … }
static int vcnl4010_read_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir)
{ … }
static int vcnl4010_config_threshold(struct iio_dev *indio_dev, bool state)
{ … }
static int vcnl4010_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
int state)
{ … }
static int vcnl4040_read_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir)
{ … }
static int vcnl4040_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir, int state)
{ … }
static irqreturn_t vcnl4040_irq_thread(int irq, void *p)
{ … }
static ssize_t vcnl4000_read_near_level(struct iio_dev *indio_dev,
uintptr_t priv,
const struct iio_chan_spec *chan,
char *buf)
{ … }
static irqreturn_t vcnl4010_irq_thread(int irq, void *p)
{ … }
static irqreturn_t vcnl4010_trigger_handler(int irq, void *p)
{ … }
static int vcnl4010_buffer_postenable(struct iio_dev *indio_dev)
{ … }
static int vcnl4010_buffer_predisable(struct iio_dev *indio_dev)
{ … }
static const struct iio_buffer_setup_ops vcnl4010_buffer_ops = …;
static const struct iio_chan_spec_ext_info vcnl4000_ext_info[] = …;
static const struct iio_event_spec vcnl4000_event_spec[] = …;
static const struct iio_event_spec vcnl4040_als_event_spec[] = …;
static const struct iio_event_spec vcnl4040_event_spec[] = …;
static const struct iio_chan_spec vcnl4000_channels[] = …;
static const struct iio_chan_spec vcnl4010_channels[] = …;
static const struct iio_chan_spec vcnl4040_channels[] = …;
static const struct iio_info vcnl4000_info = …;
static const struct iio_info vcnl4010_info = …;
static const struct iio_info vcnl4040_info = …;
static const struct vcnl4000_chip_spec vcnl4000_chip_spec_cfg[] = …;
static const struct iio_trigger_ops vcnl4010_trigger_ops = …;
static int vcnl4010_probe_trigger(struct iio_dev *indio_dev)
{ … }
static int vcnl4000_probe(struct i2c_client *client)
{ … }
static const struct of_device_id vcnl_4000_of_match[] = …;
MODULE_DEVICE_TABLE(of, vcnl_4000_of_match);
static void vcnl4000_remove(struct i2c_client *client)
{ … }
static int vcnl4000_runtime_suspend(struct device *dev)
{ … }
static int vcnl4000_runtime_resume(struct device *dev)
{ … }
static DEFINE_RUNTIME_DEV_PM_OPS(vcnl4000_pm_ops, vcnl4000_runtime_suspend,
vcnl4000_runtime_resume, NULL);
static struct i2c_driver vcnl4000_driver = …;
module_i2c_driver(…) …;
MODULE_AUTHOR(…) …;
MODULE_AUTHOR(…) …;
MODULE_DESCRIPTION(…) …;
MODULE_LICENSE(…) …;