Skip to content

Commit 14e0d91

Browse files
AbhashPLjic23
authored andcommitted
iio: light: ltr390: Add ALS channel and support for gain and resolution
Add new ALS channel and allow reading lux and scale values. Also provide gain and resolution configuration for ALS channel. Add automatic mode switching between the UVS and ALS channel based on which channel is being accessed. The default mode in which the sensor start is ALS mode. Signed-off-by: Abhash Jha <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jonathan Cameron <[email protected]>
1 parent 0a2d94e commit 14e0d91

File tree

1 file changed

+90
-15
lines changed

1 file changed

+90
-15
lines changed

drivers/iio/light/ltr390.c

Lines changed: 90 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,17 @@
6363
*/
6464
#define LTR390_WINDOW_FACTOR 1
6565

66+
enum ltr390_mode {
67+
LTR390_SET_ALS_MODE,
68+
LTR390_SET_UVS_MODE,
69+
};
70+
6671
struct ltr390_data {
6772
struct regmap *regmap;
6873
struct i2c_client *client;
6974
/* Protects device from simulataneous reads */
7075
struct mutex lock;
76+
enum ltr390_mode mode;
7177
int gain;
7278
int int_time_us;
7379
};
@@ -95,6 +101,30 @@ static int ltr390_register_read(struct ltr390_data *data, u8 register_address)
95101
return get_unaligned_le24(recieve_buffer);
96102
}
97103

104+
static int ltr390_set_mode(struct ltr390_data *data, enum ltr390_mode mode)
105+
{
106+
int ret;
107+
108+
if (data->mode == mode)
109+
return 0;
110+
111+
switch (mode) {
112+
case LTR390_SET_ALS_MODE:
113+
ret = regmap_clear_bits(data->regmap, LTR390_MAIN_CTRL, LTR390_UVS_MODE);
114+
break;
115+
116+
case LTR390_SET_UVS_MODE:
117+
ret = regmap_set_bits(data->regmap, LTR390_MAIN_CTRL, LTR390_UVS_MODE);
118+
break;
119+
}
120+
121+
if (ret)
122+
return ret;
123+
124+
data->mode = mode;
125+
return 0;
126+
}
127+
98128
static int ltr390_read_raw(struct iio_dev *iio_device,
99129
struct iio_chan_spec const *chan, int *val,
100130
int *val2, long mask)
@@ -105,15 +135,47 @@ static int ltr390_read_raw(struct iio_dev *iio_device,
105135
guard(mutex)(&data->lock);
106136
switch (mask) {
107137
case IIO_CHAN_INFO_RAW:
108-
ret = ltr390_register_read(data, LTR390_UVS_DATA);
109-
if (ret < 0)
110-
return ret;
138+
switch (chan->type) {
139+
case IIO_UVINDEX:
140+
ret = ltr390_set_mode(data, LTR390_SET_UVS_MODE);
141+
if (ret < 0)
142+
return ret;
143+
144+
ret = ltr390_register_read(data, LTR390_UVS_DATA);
145+
if (ret < 0)
146+
return ret;
147+
break;
148+
149+
case IIO_LIGHT:
150+
ret = ltr390_set_mode(data, LTR390_SET_ALS_MODE);
151+
if (ret < 0)
152+
return ret;
153+
154+
ret = ltr390_register_read(data, LTR390_ALS_DATA);
155+
if (ret < 0)
156+
return ret;
157+
break;
158+
159+
default:
160+
return -EINVAL;
161+
}
111162
*val = ret;
112163
return IIO_VAL_INT;
113164
case IIO_CHAN_INFO_SCALE:
114-
*val = LTR390_WINDOW_FACTOR;
115-
*val2 = LTR390_COUNTS_PER_UVI;
116-
return IIO_VAL_FRACTIONAL;
165+
switch (chan->type) {
166+
case IIO_UVINDEX:
167+
*val = LTR390_WINDOW_FACTOR;
168+
*val2 = LTR390_COUNTS_PER_UVI;
169+
return IIO_VAL_FRACTIONAL;
170+
171+
case IIO_LIGHT:
172+
*val = LTR390_WINDOW_FACTOR * 6 * 100;
173+
*val2 = data->gain * data->int_time_us;
174+
return IIO_VAL_FRACTIONAL;
175+
176+
default:
177+
return -EINVAL;
178+
}
117179

118180
case IIO_CHAN_INFO_INT_TIME:
119181
*val = data->int_time_us;
@@ -128,11 +190,23 @@ static int ltr390_read_raw(struct iio_dev *iio_device,
128190
static const int ltr390_int_time_map_us[] = { 400000, 200000, 100000, 50000, 25000, 12500 };
129191
static const int ltr390_gain_map[] = { 1, 3, 6, 9, 18 };
130192

131-
static const struct iio_chan_spec ltr390_channel = {
132-
.type = IIO_UVINDEX,
133-
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
134-
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME),
135-
.info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) | BIT(IIO_CHAN_INFO_SCALE)
193+
static const struct iio_chan_spec ltr390_channels[] = {
194+
/* UV sensor */
195+
{
196+
.type = IIO_UVINDEX,
197+
.scan_index = 0,
198+
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
199+
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME),
200+
.info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) | BIT(IIO_CHAN_INFO_SCALE)
201+
},
202+
/* ALS sensor */
203+
{
204+
.type = IIO_LIGHT,
205+
.scan_index = 1,
206+
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
207+
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME),
208+
.info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) | BIT(IIO_CHAN_INFO_SCALE)
209+
},
136210
};
137211

138212
static int ltr390_set_gain(struct ltr390_data *data, int val)
@@ -252,12 +326,14 @@ static int ltr390_probe(struct i2c_client *client)
252326
data->int_time_us = 100000;
253327
/* default value of gain from pg: 16 of the datasheet */
254328
data->gain = 3;
329+
/* default mode for ltr390 is ALS mode */
330+
data->mode = LTR390_SET_ALS_MODE;
255331

256332
mutex_init(&data->lock);
257333

258334
indio_dev->info = &ltr390_info;
259-
indio_dev->channels = &ltr390_channel;
260-
indio_dev->num_channels = 1;
335+
indio_dev->channels = ltr390_channels;
336+
indio_dev->num_channels = ARRAY_SIZE(ltr390_channels);
261337
indio_dev->name = "ltr390";
262338

263339
ret = regmap_read(data->regmap, LTR390_PART_ID, &part_number);
@@ -275,8 +351,7 @@ static int ltr390_probe(struct i2c_client *client)
275351
/* Wait for the registers to reset before proceeding */
276352
usleep_range(1000, 2000);
277353

278-
ret = regmap_set_bits(data->regmap, LTR390_MAIN_CTRL,
279-
LTR390_SENSOR_ENABLE | LTR390_UVS_MODE);
354+
ret = regmap_set_bits(data->regmap, LTR390_MAIN_CTRL, LTR390_SENSOR_ENABLE);
280355
if (ret)
281356
return dev_err_probe(dev, ret, "failed to enable the sensor\n");
282357

0 commit comments

Comments
 (0)