Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

iio: light: ltr390: Add configurable gain and resolution

Add support for configuring and reading the gain and resolution
(integration time). Also provide the available values for gain and
resoltion respectively via `read_avail` callback.

Signed-off-by: Abhash Jha <abhashkumarjha123@gmail.com>
Link: https://patch.msgid.link/20240731063706.25412-2-abhashkumarjha123@gmail.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Abhash Jha and committed by
Jonathan Cameron
13fad260 d6b133a6

+126 -12
+126 -12
drivers/iio/light/ltr390.c
··· 23 23 #include <linux/module.h> 24 24 #include <linux/mutex.h> 25 25 #include <linux/regmap.h> 26 + #include <linux/bitfield.h> 26 27 27 28 #include <linux/iio/iio.h> 28 29 29 30 #include <asm/unaligned.h> 30 31 31 - #define LTR390_MAIN_CTRL 0x00 32 - #define LTR390_PART_ID 0x06 33 - #define LTR390_UVS_DATA 0x10 32 + #define LTR390_MAIN_CTRL 0x00 33 + #define LTR390_ALS_UVS_MEAS_RATE 0x04 34 + #define LTR390_ALS_UVS_GAIN 0x05 35 + #define LTR390_PART_ID 0x06 36 + #define LTR390_ALS_DATA 0x0D 37 + #define LTR390_UVS_DATA 0x10 38 + #define LTR390_INT_CFG 0x19 39 + 40 + #define LTR390_PART_NUMBER_ID 0xb 41 + #define LTR390_ALS_UVS_GAIN_MASK 0x07 42 + #define LTR390_ALS_UVS_INT_TIME_MASK 0x70 43 + #define LTR390_ALS_UVS_INT_TIME(x) FIELD_PREP(LTR390_ALS_UVS_INT_TIME_MASK, (x)) 34 44 35 45 #define LTR390_SW_RESET BIT(4) 36 46 #define LTR390_UVS_MODE BIT(3) 37 47 #define LTR390_SENSOR_ENABLE BIT(1) 38 - 39 - #define LTR390_PART_NUMBER_ID 0xb 40 48 41 49 /* 42 50 * At 20-bit resolution (integration time: 400ms) and 18x gain, 2300 counts of ··· 68 60 struct i2c_client *client; 69 61 /* Protects device from simulataneous reads */ 70 62 struct mutex lock; 63 + int gain; 64 + int int_time_us; 71 65 }; 72 66 73 67 static const struct regmap_config ltr390_regmap_config = { ··· 84 74 struct device *dev = &data->client->dev; 85 75 int ret; 86 76 u8 recieve_buffer[3]; 87 - 88 - guard(mutex)(&data->lock); 89 77 90 78 ret = regmap_bulk_read(data->regmap, register_address, recieve_buffer, 91 79 sizeof(recieve_buffer)); ··· 102 94 int ret; 103 95 struct ltr390_data *data = iio_priv(iio_device); 104 96 97 + guard(mutex)(&data->lock); 105 98 switch (mask) { 106 99 case IIO_CHAN_INFO_RAW: 107 100 ret = ltr390_register_read(data, LTR390_UVS_DATA); ··· 114 105 *val = LTR390_WINDOW_FACTOR; 115 106 *val2 = LTR390_COUNTS_PER_UVI; 116 107 return IIO_VAL_FRACTIONAL; 108 + 109 + case IIO_CHAN_INFO_INT_TIME: 110 + *val = data->int_time_us; 111 + return IIO_VAL_INT; 112 + 113 + default: 114 + return -EINVAL; 115 + } 116 + } 117 + 118 + /* integration time in us */ 119 + static const int ltr390_int_time_map_us[] = { 400000, 200000, 100000, 50000, 25000, 12500 }; 120 + static const int ltr390_gain_map[] = { 1, 3, 6, 9, 18 }; 121 + 122 + static const struct iio_chan_spec ltr390_channel = { 123 + .type = IIO_UVINDEX, 124 + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), 125 + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME), 126 + .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) | BIT(IIO_CHAN_INFO_SCALE) 127 + }; 128 + 129 + static int ltr390_set_gain(struct ltr390_data *data, int val) 130 + { 131 + int ret, idx; 132 + 133 + for (idx = 0; idx < ARRAY_SIZE(ltr390_gain_map); idx++) { 134 + if (ltr390_gain_map[idx] != val) 135 + continue; 136 + 137 + guard(mutex)(&data->lock); 138 + ret = regmap_update_bits(data->regmap, 139 + LTR390_ALS_UVS_GAIN, 140 + LTR390_ALS_UVS_GAIN_MASK, idx); 141 + if (ret) 142 + return ret; 143 + 144 + data->gain = ltr390_gain_map[idx]; 145 + return 0; 146 + } 147 + 148 + return -EINVAL; 149 + } 150 + 151 + static int ltr390_set_int_time(struct ltr390_data *data, int val) 152 + { 153 + int ret, idx; 154 + 155 + for (idx = 0; idx < ARRAY_SIZE(ltr390_int_time_map_us); idx++) { 156 + if (ltr390_int_time_map_us[idx] != val) 157 + continue; 158 + 159 + guard(mutex)(&data->lock); 160 + ret = regmap_update_bits(data->regmap, 161 + LTR390_ALS_UVS_MEAS_RATE, 162 + LTR390_ALS_UVS_INT_TIME_MASK, 163 + LTR390_ALS_UVS_INT_TIME(idx)); 164 + if (ret) 165 + return ret; 166 + 167 + data->int_time_us = ltr390_int_time_map_us[idx]; 168 + return 0; 169 + } 170 + 171 + return -EINVAL; 172 + } 173 + 174 + static int ltr390_read_avail(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, 175 + const int **vals, int *type, int *length, long mask) 176 + { 177 + switch (mask) { 178 + case IIO_CHAN_INFO_SCALE: 179 + *length = ARRAY_SIZE(ltr390_gain_map); 180 + *type = IIO_VAL_INT; 181 + *vals = ltr390_gain_map; 182 + return IIO_AVAIL_LIST; 183 + case IIO_CHAN_INFO_INT_TIME: 184 + *length = ARRAY_SIZE(ltr390_int_time_map_us); 185 + *type = IIO_VAL_INT; 186 + *vals = ltr390_int_time_map_us; 187 + return IIO_AVAIL_LIST; 188 + default: 189 + return -EINVAL; 190 + } 191 + } 192 + 193 + static int ltr390_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, 194 + int val, int val2, long mask) 195 + { 196 + struct ltr390_data *data = iio_priv(indio_dev); 197 + 198 + switch (mask) { 199 + case IIO_CHAN_INFO_SCALE: 200 + if (val2 != 0) 201 + return -EINVAL; 202 + 203 + return ltr390_set_gain(data, val); 204 + 205 + case IIO_CHAN_INFO_INT_TIME: 206 + if (val2 != 0) 207 + return -EINVAL; 208 + 209 + return ltr390_set_int_time(data, val); 210 + 117 211 default: 118 212 return -EINVAL; 119 213 } ··· 224 112 225 113 static const struct iio_info ltr390_info = { 226 114 .read_raw = ltr390_read_raw, 227 - }; 228 - 229 - static const struct iio_chan_spec ltr390_channel = { 230 - .type = IIO_UVINDEX, 231 - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE) 115 + .write_raw = ltr390_write_raw, 116 + .read_avail = ltr390_read_avail, 232 117 }; 233 118 234 119 static int ltr390_probe(struct i2c_client *client) ··· 248 139 "regmap initialization failed\n"); 249 140 250 141 data->client = client; 142 + /* default value of integration time from pg: 15 of the datasheet */ 143 + data->int_time_us = 100000; 144 + /* default value of gain from pg: 16 of the datasheet */ 145 + data->gain = 3; 146 + 251 147 mutex_init(&data->lock); 252 148 253 149 indio_dev->info = &ltr390_info;