#include <linux/acpi.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/mutex.h>
#include <linux/err.h>
#include <linux/irq.h>
#include <linux/i2c.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/iio/iio.h>
#include <linux/iio/buffer.h>
#include <linux/iio/events.h>
#include <linux/iio/kfifo_buf.h>
#include <linux/iio/sysfs.h>
#define APDS9960_REGMAP_NAME …
#define APDS9960_DRV_NAME …
#define APDS9960_REG_RAM_START …
#define APDS9960_REG_RAM_END …
#define APDS9960_REG_ENABLE …
#define APDS9960_REG_ATIME …
#define APDS9960_REG_WTIME …
#define APDS9960_REG_AILTL …
#define APDS9960_REG_AILTH …
#define APDS9960_REG_AIHTL …
#define APDS9960_REG_AIHTH …
#define APDS9960_REG_PILT …
#define APDS9960_REG_PIHT …
#define APDS9960_REG_PERS …
#define APDS9960_REG_CONFIG_1 …
#define APDS9960_REG_PPULSE …
#define APDS9960_REG_CONTROL …
#define APDS9960_REG_CONTROL_AGAIN_MASK …
#define APDS9960_REG_CONTROL_PGAIN_MASK …
#define APDS9960_REG_CONTROL_AGAIN_MASK_SHIFT …
#define APDS9960_REG_CONTROL_PGAIN_MASK_SHIFT …
#define APDS9960_REG_CONFIG_2 …
#define APDS9960_REG_ID …
#define APDS9960_REG_STATUS …
#define APDS9960_REG_STATUS_PS_INT …
#define APDS9960_REG_STATUS_ALS_INT …
#define APDS9960_REG_STATUS_GINT …
#define APDS9960_REG_PDATA …
#define APDS9960_REG_POFFSET_UR …
#define APDS9960_REG_POFFSET_DL …
#define APDS9960_REG_CONFIG_3 …
#define APDS9960_REG_GPENTH …
#define APDS9960_REG_GEXTH …
#define APDS9960_REG_GCONF_1 …
#define APDS9960_REG_GCONF_1_GFIFO_THRES_MASK …
#define APDS9960_REG_GCONF_1_GFIFO_THRES_MASK_SHIFT …
#define APDS9960_REG_GCONF_2 …
#define APDS9960_REG_GCONF_2_GGAIN_MASK …
#define APDS9960_REG_GCONF_2_GGAIN_MASK_SHIFT …
#define APDS9960_REG_GOFFSET_U …
#define APDS9960_REG_GOFFSET_D …
#define APDS9960_REG_GPULSE …
#define APDS9960_REG_GOFFSET_L …
#define APDS9960_REG_GOFFSET_R …
#define APDS9960_REG_GCONF_3 …
#define APDS9960_REG_GCONF_4 …
#define APDS9960_REG_GFLVL …
#define APDS9960_REG_GSTATUS …
#define APDS9960_REG_IFORCE …
#define APDS9960_REG_PICLEAR …
#define APDS9960_REG_CICLEAR …
#define APDS9960_REG_AICLEAR …
#define APDS9960_DEFAULT_PERS …
#define APDS9960_DEFAULT_GPENTH …
#define APDS9960_DEFAULT_GEXTH …
#define APDS9960_MAX_PXS_THRES_VAL …
#define APDS9960_MAX_ALS_THRES_VAL …
#define APDS9960_MAX_INT_TIME_IN_US …
enum apds9960_als_channel_idx { … };
#define APDS9960_REG_ALS_BASE …
#define APDS9960_REG_ALS_CHANNEL(_colour) …
enum apds9960_gesture_channel_idx { … };
#define APDS9960_REG_GFIFO_BASE …
#define APDS9960_REG_GFIFO_DIR(_dir) …
struct apds9960_data { … };
enum { … };
static const unsigned int apds9960_offset_regs[][2] = …;
static const struct reg_default apds9960_reg_defaults[] = …;
static const struct regmap_range apds9960_volatile_ranges[] = …;
static const struct regmap_access_table apds9960_volatile_table = …;
static const struct regmap_range apds9960_precious_ranges[] = …;
static const struct regmap_access_table apds9960_precious_table = …;
static const struct regmap_range apds9960_readable_ranges[] = …;
static const struct regmap_access_table apds9960_readable_table = …;
static const struct regmap_range apds9960_writeable_ranges[] = …;
static const struct regmap_access_table apds9960_writeable_table = …;
static const struct regmap_config apds9960_regmap_config = …;
static const struct iio_event_spec apds9960_pxs_event_spec[] = …;
static const struct iio_event_spec apds9960_als_event_spec[] = …;
#define APDS9960_GESTURE_CHANNEL(_dir, _si) …
#define APDS9960_INTENSITY_CHANNEL(_colour) …
static const unsigned long apds9960_scan_masks[] = …;
static const struct iio_chan_spec apds9960_channels[] = …;
static int apds9960_set_calibbias(struct apds9960_data *data,
struct iio_chan_spec const *chan, int calibbias)
{ … }
static const int apds9960_int_time[][2] = …;
static const int apds9960_pxs_gain_map[] = …;
static const int apds9960_als_gain_map[] = …;
static IIO_CONST_ATTR(proximity_scale_available, "1 2 4 8");
static IIO_CONST_ATTR(intensity_scale_available, "1 4 16 64");
static IIO_CONST_ATTR_INT_TIME_AVAIL("0.028 0.1 0.2 0.7");
static struct attribute *apds9960_attributes[] = …;
static const struct attribute_group apds9960_attribute_group = …;
static const struct reg_field apds9960_reg_field_int_als = …;
static const struct reg_field apds9960_reg_field_int_ges = …;
static const struct reg_field apds9960_reg_field_int_pxs = …;
static const struct reg_field apds9960_reg_field_enable_als = …;
static const struct reg_field apds9960_reg_field_enable_ges = …;
static const struct reg_field apds9960_reg_field_enable_pxs = …;
static int apds9960_set_it_time(struct apds9960_data *data, int val2)
{ … }
static int apds9960_set_pxs_gain(struct apds9960_data *data, int val)
{ … }
static int apds9960_set_als_gain(struct apds9960_data *data, int val)
{ … }
#ifdef CONFIG_PM
static int apds9960_set_power_state(struct apds9960_data *data, bool on)
{ … }
#else
static int apds9960_set_power_state(struct apds9960_data *data, bool on)
{
return 0;
}
#endif
static int apds9960_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct apds9960_data *data = iio_priv(indio_dev);
__le16 buf;
int ret = -EINVAL;
if (data->gesture_mode_running)
return -EBUSY;
switch (mask) {
case IIO_CHAN_INFO_RAW:
apds9960_set_power_state(data, true);
switch (chan->type) {
case IIO_PROXIMITY:
ret = regmap_read(data->regmap, chan->address, val);
if (!ret)
ret = IIO_VAL_INT;
break;
case IIO_INTENSITY:
ret = regmap_bulk_read(data->regmap, chan->address,
&buf, 2);
if (!ret) {
ret = IIO_VAL_INT;
*val = le16_to_cpu(buf);
}
break;
default:
ret = -EINVAL;
}
apds9960_set_power_state(data, false);
break;
case IIO_CHAN_INFO_INT_TIME:
mutex_lock(&data->lock);
switch (chan->type) {
case IIO_INTENSITY:
*val = 0;
*val2 = data->als_adc_int_us;
ret = IIO_VAL_INT_PLUS_MICRO;
break;
default:
ret = -EINVAL;
}
mutex_unlock(&data->lock);
break;
case IIO_CHAN_INFO_SCALE:
mutex_lock(&data->lock);
switch (chan->type) {
case IIO_PROXIMITY:
*val = apds9960_pxs_gain_map[data->pxs_gain];
ret = IIO_VAL_INT;
break;
case IIO_INTENSITY:
*val = apds9960_als_gain_map[data->als_gain];
ret = IIO_VAL_INT;
break;
default:
ret = -EINVAL;
}
mutex_unlock(&data->lock);
break;
case IIO_CHAN_INFO_CALIBBIAS:
mutex_lock(&data->lock);
*val = data->calibbias[chan->channel];
ret = IIO_VAL_INT;
mutex_unlock(&data->lock);
break;
}
return ret;
};
static int apds9960_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val, int val2, long mask)
{ … }
static inline int apds9960_get_thres_reg(const struct iio_chan_spec *chan,
enum iio_event_direction dir,
u8 *reg)
{ … }
static int apds9960_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 apds9960_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 apds9960_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 apds9960_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 const struct iio_info apds9960_info = …;
static inline int apds9660_fifo_is_empty(struct apds9960_data *data)
{ … }
static void apds9960_read_gesture_fifo(struct apds9960_data *data)
{ … }
static irqreturn_t apds9960_interrupt_handler(int irq, void *private)
{ … }
static int apds9960_set_powermode(struct apds9960_data *data, bool state)
{ … }
static int apds9960_buffer_postenable(struct iio_dev *indio_dev)
{ … }
static int apds9960_buffer_predisable(struct iio_dev *indio_dev)
{ … }
static const struct iio_buffer_setup_ops apds9960_buffer_setup_ops = …;
static int apds9960_regfield_init(struct apds9960_data *data)
{ … }
static int apds9960_chip_init(struct apds9960_data *data)
{ … }
static int apds9960_probe(struct i2c_client *client)
{ … }
static void apds9960_remove(struct i2c_client *client)
{ … }
#ifdef CONFIG_PM
static int apds9960_runtime_suspend(struct device *dev)
{ … }
static int apds9960_runtime_resume(struct device *dev)
{ … }
#endif
static const struct dev_pm_ops apds9960_pm_ops = …;
static const struct i2c_device_id apds9960_id[] = …;
MODULE_DEVICE_TABLE(i2c, apds9960_id);
static const struct acpi_device_id apds9960_acpi_match[] = …;
MODULE_DEVICE_TABLE(acpi, apds9960_acpi_match);
static const struct of_device_id apds9960_of_match[] = …;
MODULE_DEVICE_TABLE(of, apds9960_of_match);
static struct i2c_driver apds9960_driver = …;
module_i2c_driver(…) …;
MODULE_AUTHOR(…) …;
MODULE_DESCRIPTION(…) …;
MODULE_LICENSE(…) …;