Skip to content

Commit

Permalink
iio: ltr501: Add light channel support
Browse files Browse the repository at this point in the history
Added support to calculate lux value from visible
and IR spectrum adc count values. Also added IIO_LIGHT
channel to enable user read the lux value directly
from device using illuminance input ABI.

Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
  • Loading branch information
Kuppuswamy Sathyanarayanan authored and Jonathan Cameron committed May 17, 2015
1 parent c24e7da commit c06cee8
Showing 1 changed file with 51 additions and 0 deletions.
51 changes: 51 additions & 0 deletions drivers/iio/light/ltr501.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@

#define LTR501_REGMAP_NAME "ltr501_regmap"

#define LTR501_LUX_CONV(vis_coeff, vis_data, ir_coeff, ir_data) \
((vis_coeff * vis_data) - (ir_coeff * ir_data))

static const int int_time_mapping[] = {100000, 50000, 200000, 400000};

static const struct reg_field reg_field_it =
Expand Down Expand Up @@ -298,6 +301,29 @@ static int ltr501_ps_read_samp_period(struct ltr501_data *data, int *val)
return IIO_VAL_INT;
}

/* IR and visible spectrum coeff's are given in data sheet */
static unsigned long ltr501_calculate_lux(u16 vis_data, u16 ir_data)
{
unsigned long ratio, lux;

if (vis_data == 0)
return 0;

/* multiply numerator by 100 to avoid handling ratio < 1 */
ratio = DIV_ROUND_UP(ir_data * 100, ir_data + vis_data);

if (ratio < 45)
lux = LTR501_LUX_CONV(1774, vis_data, -1105, ir_data);
else if (ratio >= 45 && ratio < 64)
lux = LTR501_LUX_CONV(3772, vis_data, 1336, ir_data);
else if (ratio >= 64 && ratio < 85)
lux = LTR501_LUX_CONV(1690, vis_data, 169, ir_data);
else
lux = 0;

return lux / 1000;
}

static int ltr501_drdy(struct ltr501_data *data, u8 drdy_mask)
{
int tries = 100;
Expand Down Expand Up @@ -548,7 +574,14 @@ static const struct iio_event_spec ltr501_pxs_event_spec[] = {
.num_event_specs = _evsize,\
}

#define LTR501_LIGHT_CHANNEL() { \
.type = IIO_LIGHT, \
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \
.scan_index = -1, \
}

static const struct iio_chan_spec ltr501_channels[] = {
LTR501_LIGHT_CHANNEL(),
LTR501_INTENSITY_CHANNEL(0, LTR501_ALS_DATA0, IIO_MOD_LIGHT_BOTH, 0,
ltr501_als_event_spec,
ARRAY_SIZE(ltr501_als_event_spec)),
Expand Down Expand Up @@ -576,6 +609,7 @@ static const struct iio_chan_spec ltr501_channels[] = {
};

static const struct iio_chan_spec ltr301_channels[] = {
LTR501_LIGHT_CHANNEL(),
LTR501_INTENSITY_CHANNEL(0, LTR501_ALS_DATA0, IIO_MOD_LIGHT_BOTH, 0,
ltr501_als_event_spec,
ARRAY_SIZE(ltr501_als_event_spec)),
Expand All @@ -596,6 +630,23 @@ static int ltr501_read_raw(struct iio_dev *indio_dev,
int ret, i;

switch (mask) {
case IIO_CHAN_INFO_PROCESSED:
if (iio_buffer_enabled(indio_dev))
return -EBUSY;

switch (chan->type) {
case IIO_LIGHT:
mutex_lock(&data->lock_als);
ret = ltr501_read_als(data, buf);
mutex_unlock(&data->lock_als);
if (ret < 0)
return ret;
*val = ltr501_calculate_lux(le16_to_cpu(buf[1]),
le16_to_cpu(buf[0]));
return IIO_VAL_INT;
default:
return -EINVAL;
}
case IIO_CHAN_INFO_RAW:
if (iio_buffer_enabled(indio_dev))
return -EBUSY;
Expand Down

0 comments on commit c06cee8

Please sign in to comment.