ltr390.c (13fad2607dad14afd0633d9c869499f6e7c998bd) | ltr390.c (14e0d914a855f9ad2669c0a2ed35f0003f771be5) |
---|---|
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * IIO driver for Lite-On LTR390 ALS and UV sensor 4 * (7-bit I2C slave address 0x53) 5 * 6 * Based on the work of: 7 * Shreeya Patel and Shi Zhigang (LTRF216 Driver) 8 * --- 49 unchanged lines hidden (view full) --- 58 59/* 60 * Window Factor is needed when the device is under Window glass with coated 61 * tinted ink. This is to compensate for the light loss due to the lower 62 * transmission rate of the window glass and helps * in calculating lux. 63 */ 64#define LTR390_WINDOW_FACTOR 1 65 | 1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * IIO driver for Lite-On LTR390 ALS and UV sensor 4 * (7-bit I2C slave address 0x53) 5 * 6 * Based on the work of: 7 * Shreeya Patel and Shi Zhigang (LTRF216 Driver) 8 * --- 49 unchanged lines hidden (view full) --- 58 59/* 60 * Window Factor is needed when the device is under Window glass with coated 61 * tinted ink. This is to compensate for the light loss due to the lower 62 * transmission rate of the window glass and helps * in calculating lux. 63 */ 64#define LTR390_WINDOW_FACTOR 1 65 |
66enum ltr390_mode { 67 LTR390_SET_ALS_MODE, 68 LTR390_SET_UVS_MODE, 69}; 70 |
|
66struct ltr390_data { 67 struct regmap *regmap; 68 struct i2c_client *client; 69 /* Protects device from simulataneous reads */ 70 struct mutex lock; | 71struct ltr390_data { 72 struct regmap *regmap; 73 struct i2c_client *client; 74 /* Protects device from simulataneous reads */ 75 struct mutex lock; |
76 enum ltr390_mode mode; |
|
71 int gain; 72 int int_time_us; 73}; 74 75static const struct regmap_config ltr390_regmap_config = { 76 .name = "ltr390", 77 .reg_bits = 8, 78 .reg_stride = 1, --- 11 unchanged lines hidden (view full) --- 90 if (ret) { 91 dev_err(dev, "failed to read measurement data"); 92 return ret; 93 } 94 95 return get_unaligned_le24(recieve_buffer); 96} 97 | 77 int gain; 78 int int_time_us; 79}; 80 81static const struct regmap_config ltr390_regmap_config = { 82 .name = "ltr390", 83 .reg_bits = 8, 84 .reg_stride = 1, --- 11 unchanged lines hidden (view full) --- 96 if (ret) { 97 dev_err(dev, "failed to read measurement data"); 98 return ret; 99 } 100 101 return get_unaligned_le24(recieve_buffer); 102} 103 |
104static 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 |
|
98static int ltr390_read_raw(struct iio_dev *iio_device, 99 struct iio_chan_spec const *chan, int *val, 100 int *val2, long mask) 101{ 102 int ret; 103 struct ltr390_data *data = iio_priv(iio_device); 104 105 guard(mutex)(&data->lock); 106 switch (mask) { 107 case IIO_CHAN_INFO_RAW: | 128static int ltr390_read_raw(struct iio_dev *iio_device, 129 struct iio_chan_spec const *chan, int *val, 130 int *val2, long mask) 131{ 132 int ret; 133 struct ltr390_data *data = iio_priv(iio_device); 134 135 guard(mutex)(&data->lock); 136 switch (mask) { 137 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 } |
111 *val = ret; 112 return IIO_VAL_INT; 113 case IIO_CHAN_INFO_SCALE: | 162 *val = ret; 163 return IIO_VAL_INT; 164 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; |
117 | 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 } 179 |
|
118 case IIO_CHAN_INFO_INT_TIME: 119 *val = data->int_time_us; 120 return IIO_VAL_INT; 121 122 default: 123 return -EINVAL; 124 } 125} 126 127/* integration time in us */ 128static const int ltr390_int_time_map_us[] = { 400000, 200000, 100000, 50000, 25000, 12500 }; 129static const int ltr390_gain_map[] = { 1, 3, 6, 9, 18 }; 130 | 180 case IIO_CHAN_INFO_INT_TIME: 181 *val = data->int_time_us; 182 return IIO_VAL_INT; 183 184 default: 185 return -EINVAL; 186 } 187} 188 189/* integration time in us */ 190static const int ltr390_int_time_map_us[] = { 400000, 200000, 100000, 50000, 25000, 12500 }; 191static const int ltr390_gain_map[] = { 1, 3, 6, 9, 18 }; 192 |
131static 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) | 193static 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 }, |
136}; 137 138static int ltr390_set_gain(struct ltr390_data *data, int val) 139{ 140 int ret, idx; 141 142 for (idx = 0; idx < ARRAY_SIZE(ltr390_gain_map); idx++) { 143 if (ltr390_gain_map[idx] != val) --- 103 unchanged lines hidden (view full) --- 247 return dev_err_probe(dev, PTR_ERR(data->regmap), 248 "regmap initialization failed\n"); 249 250 data->client = client; 251 /* default value of integration time from pg: 15 of the datasheet */ 252 data->int_time_us = 100000; 253 /* default value of gain from pg: 16 of the datasheet */ 254 data->gain = 3; | 210}; 211 212static int ltr390_set_gain(struct ltr390_data *data, int val) 213{ 214 int ret, idx; 215 216 for (idx = 0; idx < ARRAY_SIZE(ltr390_gain_map); idx++) { 217 if (ltr390_gain_map[idx] != val) --- 103 unchanged lines hidden (view full) --- 321 return dev_err_probe(dev, PTR_ERR(data->regmap), 322 "regmap initialization failed\n"); 323 324 data->client = client; 325 /* default value of integration time from pg: 15 of the datasheet */ 326 data->int_time_us = 100000; 327 /* default value of gain from pg: 16 of the datasheet */ 328 data->gain = 3; |
329 /* default mode for ltr390 is ALS mode */ 330 data->mode = LTR390_SET_ALS_MODE; |
|
255 256 mutex_init(&data->lock); 257 258 indio_dev->info = <r390_info; | 331 332 mutex_init(&data->lock); 333 334 indio_dev->info = <r390_info; |
259 indio_dev->channels = <r390_channel; 260 indio_dev->num_channels = 1; | 335 indio_dev->channels = ltr390_channels; 336 indio_dev->num_channels = ARRAY_SIZE(ltr390_channels); |
261 indio_dev->name = "ltr390"; 262 263 ret = regmap_read(data->regmap, LTR390_PART_ID, &part_number); 264 if (ret) 265 return dev_err_probe(dev, ret, 266 "failed to get sensor's part id\n"); 267 /* Lower 4 bits of `part_number` change with hardware revisions */ 268 if (part_number >> 4 != LTR390_PART_NUMBER_ID) 269 dev_info(dev, "received invalid product id: 0x%x", part_number); 270 dev_dbg(dev, "LTR390, product id: 0x%x\n", part_number); 271 272 /* reset sensor, chip fails to respond to this, so ignore any errors */ 273 regmap_set_bits(data->regmap, LTR390_MAIN_CTRL, LTR390_SW_RESET); 274 275 /* Wait for the registers to reset before proceeding */ 276 usleep_range(1000, 2000); 277 | 337 indio_dev->name = "ltr390"; 338 339 ret = regmap_read(data->regmap, LTR390_PART_ID, &part_number); 340 if (ret) 341 return dev_err_probe(dev, ret, 342 "failed to get sensor's part id\n"); 343 /* Lower 4 bits of `part_number` change with hardware revisions */ 344 if (part_number >> 4 != LTR390_PART_NUMBER_ID) 345 dev_info(dev, "received invalid product id: 0x%x", part_number); 346 dev_dbg(dev, "LTR390, product id: 0x%x\n", part_number); 347 348 /* reset sensor, chip fails to respond to this, so ignore any errors */ 349 regmap_set_bits(data->regmap, LTR390_MAIN_CTRL, LTR390_SW_RESET); 350 351 /* Wait for the registers to reset before proceeding */ 352 usleep_range(1000, 2000); 353 |
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); |
280 if (ret) 281 return dev_err_probe(dev, ret, "failed to enable the sensor\n"); 282 283 return devm_iio_device_register(dev, indio_dev); 284} 285 286static const struct i2c_device_id ltr390_id[] = { 287 { "ltr390" }, --- 23 unchanged lines hidden --- | 355 if (ret) 356 return dev_err_probe(dev, ret, "failed to enable the sensor\n"); 357 358 return devm_iio_device_register(dev, indio_dev); 359} 360 361static const struct i2c_device_id ltr390_id[] = { 362 { "ltr390" }, --- 23 unchanged lines hidden --- |