mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
iio: vcnl4000: Add sampling frequency support for VCNL4010/20.
Add sampling frequency support for proximity data on VCNL4010 and VCNL4020 chips. Signed-off-by: Mathieu Othacehe <m.othacehe@gmail.com> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
This commit is contained in:
parent
d35567fcaf
commit
f6889c1b00
1 changed files with 117 additions and 1 deletions
|
@ -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 */
|
||||
|
||||
|
@ -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;
|
||||
|
@ -457,11 +485,95 @@ 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,
|
||||
const struct iio_chan_spec *chan,
|
||||
enum iio_event_type type,
|
||||
|
@ -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,
|
||||
|
@ -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…
Add table
Reference in a new issue