Loading drivers/iio/light/vcnl4000.c +117 −1 Original line number Diff line number Diff line Loading @@ -86,6 +86,16 @@ #define VCNL4010_INT_DRDY \ (BIT(VCNL4010_INT_PROXIMITY) | BIT(VCNL4010_INT_ALS)) static const int vcnl4010_prox_sampling_frequency[][2] = { {1, 950000}, {3, 906250}, {7, 812500}, {16, 625000}, {31, 250000}, {62, 500000}, {125, 0}, {250, 0}, }; #define VCNL4000_SLEEP_DELAY_MS 2000 /* before we enter pm_runtime_suspend */ Loading Loading @@ -364,6 +374,24 @@ static int vcnl4200_measure_proximity(struct vcnl4000_data *data, int *val) return vcnl4200_measure(data, &data->vcnl4200_ps, val); } static int vcnl4010_read_proxy_samp_freq(struct vcnl4000_data *data, int *val, int *val2) { int ret; ret = i2c_smbus_read_byte_data(data->client, VCNL4010_PROX_RATE); if (ret < 0) return ret; if (ret >= ARRAY_SIZE(vcnl4010_prox_sampling_frequency)) return -EINVAL; *val = vcnl4010_prox_sampling_frequency[ret][0]; *val2 = vcnl4010_prox_sampling_frequency[ret][1]; return 0; } static bool vcnl4010_is_in_periodic_mode(struct vcnl4000_data *data) { int ret; Loading Loading @@ -457,9 +485,93 @@ static int vcnl4010_read_raw(struct iio_dev *indio_dev, iio_device_release_direct_mode(indio_dev); return ret; case IIO_CHAN_INFO_SAMP_FREQ: switch (chan->type) { case IIO_PROXIMITY: ret = vcnl4010_read_proxy_samp_freq(data, val, val2); if (ret < 0) return ret; return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; } default: return -EINVAL; } } 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) { switch (mask) { case IIO_CHAN_INFO_SAMP_FREQ: *vals = (int *)vcnl4010_prox_sampling_frequency; *type = IIO_VAL_INT_PLUS_MICRO; *length = 2 * ARRAY_SIZE(vcnl4010_prox_sampling_frequency); return IIO_AVAIL_LIST; default: return -EINVAL; } } static int vcnl4010_write_proxy_samp_freq(struct vcnl4000_data *data, int val, int val2) { unsigned int i; int index = -1; for (i = 0; i < ARRAY_SIZE(vcnl4010_prox_sampling_frequency); i++) { if (val == vcnl4010_prox_sampling_frequency[i][0] && val2 == vcnl4010_prox_sampling_frequency[i][1]) { index = i; break; } } if (index < 0) return -EINVAL; return i2c_smbus_write_byte_data(data->client, VCNL4010_PROX_RATE, index); } static int vcnl4010_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask) { int ret; struct vcnl4000_data *data = iio_priv(indio_dev); ret = iio_device_claim_direct_mode(indio_dev); if (ret) return ret; /* Protect against event capture. */ if (vcnl4010_is_in_periodic_mode(data)) { ret = -EBUSY; goto end; } switch (mask) { case IIO_CHAN_INFO_SAMP_FREQ: switch (chan->type) { case IIO_PROXIMITY: ret = vcnl4010_write_proxy_samp_freq(data, val, val2); goto end; default: ret = -EINVAL; goto end; } default: ret = -EINVAL; goto end; } end: iio_device_release_direct_mode(indio_dev); return ret; } static int vcnl4010_read_event(struct iio_dev *indio_dev, Loading Loading @@ -664,7 +776,9 @@ static const struct iio_chan_spec vcnl4010_channels[] = { BIT(IIO_CHAN_INFO_SCALE), }, { .type = IIO_PROXIMITY, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SAMP_FREQ), .info_mask_separate_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), .event_spec = vcnl4000_event_spec, .num_event_specs = ARRAY_SIZE(vcnl4000_event_spec), .ext_info = vcnl4000_ext_info, Loading @@ -677,6 +791,8 @@ static const struct iio_info vcnl4000_info = { static const struct iio_info vcnl4010_info = { .read_raw = vcnl4010_read_raw, .read_avail = vcnl4010_read_avail, .write_raw = vcnl4010_write_raw, .read_event_value = vcnl4010_read_event, .write_event_value = vcnl4010_write_event, .read_event_config = vcnl4010_read_event_config, Loading Loading
drivers/iio/light/vcnl4000.c +117 −1 Original line number Diff line number Diff line Loading @@ -86,6 +86,16 @@ #define VCNL4010_INT_DRDY \ (BIT(VCNL4010_INT_PROXIMITY) | BIT(VCNL4010_INT_ALS)) static const int vcnl4010_prox_sampling_frequency[][2] = { {1, 950000}, {3, 906250}, {7, 812500}, {16, 625000}, {31, 250000}, {62, 500000}, {125, 0}, {250, 0}, }; #define VCNL4000_SLEEP_DELAY_MS 2000 /* before we enter pm_runtime_suspend */ Loading Loading @@ -364,6 +374,24 @@ static int vcnl4200_measure_proximity(struct vcnl4000_data *data, int *val) return vcnl4200_measure(data, &data->vcnl4200_ps, val); } static int vcnl4010_read_proxy_samp_freq(struct vcnl4000_data *data, int *val, int *val2) { int ret; ret = i2c_smbus_read_byte_data(data->client, VCNL4010_PROX_RATE); if (ret < 0) return ret; if (ret >= ARRAY_SIZE(vcnl4010_prox_sampling_frequency)) return -EINVAL; *val = vcnl4010_prox_sampling_frequency[ret][0]; *val2 = vcnl4010_prox_sampling_frequency[ret][1]; return 0; } static bool vcnl4010_is_in_periodic_mode(struct vcnl4000_data *data) { int ret; Loading Loading @@ -457,9 +485,93 @@ static int vcnl4010_read_raw(struct iio_dev *indio_dev, iio_device_release_direct_mode(indio_dev); return ret; case IIO_CHAN_INFO_SAMP_FREQ: switch (chan->type) { case IIO_PROXIMITY: ret = vcnl4010_read_proxy_samp_freq(data, val, val2); if (ret < 0) return ret; return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; } default: return -EINVAL; } } 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) { switch (mask) { case IIO_CHAN_INFO_SAMP_FREQ: *vals = (int *)vcnl4010_prox_sampling_frequency; *type = IIO_VAL_INT_PLUS_MICRO; *length = 2 * ARRAY_SIZE(vcnl4010_prox_sampling_frequency); return IIO_AVAIL_LIST; default: return -EINVAL; } } static int vcnl4010_write_proxy_samp_freq(struct vcnl4000_data *data, int val, int val2) { unsigned int i; int index = -1; for (i = 0; i < ARRAY_SIZE(vcnl4010_prox_sampling_frequency); i++) { if (val == vcnl4010_prox_sampling_frequency[i][0] && val2 == vcnl4010_prox_sampling_frequency[i][1]) { index = i; break; } } if (index < 0) return -EINVAL; return i2c_smbus_write_byte_data(data->client, VCNL4010_PROX_RATE, index); } static int vcnl4010_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask) { int ret; struct vcnl4000_data *data = iio_priv(indio_dev); ret = iio_device_claim_direct_mode(indio_dev); if (ret) return ret; /* Protect against event capture. */ if (vcnl4010_is_in_periodic_mode(data)) { ret = -EBUSY; goto end; } switch (mask) { case IIO_CHAN_INFO_SAMP_FREQ: switch (chan->type) { case IIO_PROXIMITY: ret = vcnl4010_write_proxy_samp_freq(data, val, val2); goto end; default: ret = -EINVAL; goto end; } default: ret = -EINVAL; goto end; } end: iio_device_release_direct_mode(indio_dev); return ret; } static int vcnl4010_read_event(struct iio_dev *indio_dev, Loading Loading @@ -664,7 +776,9 @@ static const struct iio_chan_spec vcnl4010_channels[] = { BIT(IIO_CHAN_INFO_SCALE), }, { .type = IIO_PROXIMITY, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SAMP_FREQ), .info_mask_separate_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), .event_spec = vcnl4000_event_spec, .num_event_specs = ARRAY_SIZE(vcnl4000_event_spec), .ext_info = vcnl4000_ext_info, Loading @@ -677,6 +791,8 @@ static const struct iio_info vcnl4000_info = { static const struct iio_info vcnl4010_info = { .read_raw = vcnl4010_read_raw, .read_avail = vcnl4010_read_avail, .write_raw = vcnl4010_write_raw, .read_event_value = vcnl4010_read_event, .write_event_value = vcnl4010_write_event, .read_event_config = vcnl4010_read_event_config, Loading