diff options
Diffstat (limited to 'drivers/iio/light/max44000.c')
-rw-r--r-- | drivers/iio/light/max44000.c | 639 |
1 files changed, 639 insertions, 0 deletions
diff --git a/drivers/iio/light/max44000.c b/drivers/iio/light/max44000.c new file mode 100644 index 000000000000..e01e58a9bd14 --- /dev/null +++ b/drivers/iio/light/max44000.c | |||
@@ -0,0 +1,639 @@ | |||
1 | /* | ||
2 | * MAX44000 Ambient and Infrared Proximity Sensor | ||
3 | * | ||
4 | * Copyright (c) 2016, Intel Corporation. | ||
5 | * | ||
6 | * This file is subject to the terms and conditions of version 2 of | ||
7 | * the GNU General Public License. See the file COPYING in the main | ||
8 | * directory of this archive for more details. | ||
9 | * | ||
10 | * Data sheet: https://datasheets.maximintegrated.com/en/ds/MAX44000.pdf | ||
11 | * | ||
12 | * 7-bit I2C slave address 0x4a | ||
13 | */ | ||
14 | |||
15 | #include <linux/module.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/i2c.h> | ||
18 | #include <linux/regmap.h> | ||
19 | #include <linux/util_macros.h> | ||
20 | #include <linux/iio/iio.h> | ||
21 | #include <linux/iio/sysfs.h> | ||
22 | #include <linux/iio/buffer.h> | ||
23 | #include <linux/iio/trigger_consumer.h> | ||
24 | #include <linux/iio/triggered_buffer.h> | ||
25 | #include <linux/acpi.h> | ||
26 | |||
27 | #define MAX44000_DRV_NAME "max44000" | ||
28 | |||
29 | /* Registers in datasheet order */ | ||
30 | #define MAX44000_REG_STATUS 0x00 | ||
31 | #define MAX44000_REG_CFG_MAIN 0x01 | ||
32 | #define MAX44000_REG_CFG_RX 0x02 | ||
33 | #define MAX44000_REG_CFG_TX 0x03 | ||
34 | #define MAX44000_REG_ALS_DATA_HI 0x04 | ||
35 | #define MAX44000_REG_ALS_DATA_LO 0x05 | ||
36 | #define MAX44000_REG_PRX_DATA 0x16 | ||
37 | #define MAX44000_REG_ALS_UPTHR_HI 0x06 | ||
38 | #define MAX44000_REG_ALS_UPTHR_LO 0x07 | ||
39 | #define MAX44000_REG_ALS_LOTHR_HI 0x08 | ||
40 | #define MAX44000_REG_ALS_LOTHR_LO 0x09 | ||
41 | #define MAX44000_REG_PST 0x0a | ||
42 | #define MAX44000_REG_PRX_IND 0x0b | ||
43 | #define MAX44000_REG_PRX_THR 0x0c | ||
44 | #define MAX44000_REG_TRIM_GAIN_GREEN 0x0f | ||
45 | #define MAX44000_REG_TRIM_GAIN_IR 0x10 | ||
46 | |||
47 | /* REG_CFG bits */ | ||
48 | #define MAX44000_CFG_ALSINTE 0x01 | ||
49 | #define MAX44000_CFG_PRXINTE 0x02 | ||
50 | #define MAX44000_CFG_MASK 0x1c | ||
51 | #define MAX44000_CFG_MODE_SHUTDOWN 0x00 | ||
52 | #define MAX44000_CFG_MODE_ALS_GIR 0x04 | ||
53 | #define MAX44000_CFG_MODE_ALS_G 0x08 | ||
54 | #define MAX44000_CFG_MODE_ALS_IR 0x0c | ||
55 | #define MAX44000_CFG_MODE_ALS_PRX 0x10 | ||
56 | #define MAX44000_CFG_MODE_PRX 0x14 | ||
57 | #define MAX44000_CFG_TRIM 0x20 | ||
58 | |||
59 | /* | ||
60 | * Upper 4 bits are not documented but start as 1 on powerup | ||
61 | * Setting them to 0 causes proximity to misbehave so set them to 1 | ||
62 | */ | ||
63 | #define MAX44000_REG_CFG_RX_DEFAULT 0xf0 | ||
64 | |||
65 | /* REG_RX bits */ | ||
66 | #define MAX44000_CFG_RX_ALSTIM_MASK 0x0c | ||
67 | #define MAX44000_CFG_RX_ALSTIM_SHIFT 2 | ||
68 | #define MAX44000_CFG_RX_ALSPGA_MASK 0x03 | ||
69 | #define MAX44000_CFG_RX_ALSPGA_SHIFT 0 | ||
70 | |||
71 | /* REG_TX bits */ | ||
72 | #define MAX44000_LED_CURRENT_MASK 0xf | ||
73 | #define MAX44000_LED_CURRENT_MAX 11 | ||
74 | #define MAX44000_LED_CURRENT_DEFAULT 6 | ||
75 | |||
76 | #define MAX44000_ALSDATA_OVERFLOW 0x4000 | ||
77 | |||
78 | struct max44000_data { | ||
79 | struct mutex lock; | ||
80 | struct regmap *regmap; | ||
81 | }; | ||
82 | |||
83 | /* Default scale is set to the minimum of 0.03125 or 1 / (1 << 5) lux */ | ||
84 | #define MAX44000_ALS_TO_LUX_DEFAULT_FRACTION_LOG2 5 | ||
85 | |||
86 | /* Scale can be multiplied by up to 128x via ALSPGA for measurement gain */ | ||
87 | static const int max44000_alspga_shift[] = {0, 2, 4, 7}; | ||
88 | #define MAX44000_ALSPGA_MAX_SHIFT 7 | ||
89 | |||
90 | /* | ||
91 | * Scale can be multiplied by up to 64x via ALSTIM because of lost resolution | ||
92 | * | ||
93 | * This scaling factor is hidden from userspace and instead accounted for when | ||
94 | * reading raw values from the device. | ||
95 | * | ||
96 | * This makes it possible to cleanly expose ALSPGA as IIO_CHAN_INFO_SCALE and | ||
97 | * ALSTIM as IIO_CHAN_INFO_INT_TIME without the values affecting each other. | ||
98 | * | ||
99 | * Handling this internally is also required for buffer support because the | ||
100 | * channel's scan_type can't be modified dynamically. | ||
101 | */ | ||
102 | static const int max44000_alstim_shift[] = {0, 2, 4, 6}; | ||
103 | #define MAX44000_ALSTIM_SHIFT(alstim) (2 * (alstim)) | ||
104 | |||
105 | /* Available integration times with pretty manual alignment: */ | ||
106 | static const int max44000_int_time_avail_ns_array[] = { | ||
107 | 100000000, | ||
108 | 25000000, | ||
109 | 6250000, | ||
110 | 1562500, | ||
111 | }; | ||
112 | static const char max44000_int_time_avail_str[] = | ||
113 | "0.100 " | ||
114 | "0.025 " | ||
115 | "0.00625 " | ||
116 | "0.001625"; | ||
117 | |||
118 | /* Available scales (internal to ulux) with pretty manual alignment: */ | ||
119 | static const int max44000_scale_avail_ulux_array[] = { | ||
120 | 31250, | ||
121 | 125000, | ||
122 | 500000, | ||
123 | 4000000, | ||
124 | }; | ||
125 | static const char max44000_scale_avail_str[] = | ||
126 | "0.03125 " | ||
127 | "0.125 " | ||
128 | "0.5 " | ||
129 | "4"; | ||
130 | |||
131 | #define MAX44000_SCAN_INDEX_ALS 0 | ||
132 | #define MAX44000_SCAN_INDEX_PRX 1 | ||
133 | |||
134 | static const struct iio_chan_spec max44000_channels[] = { | ||
135 | { | ||
136 | .type = IIO_LIGHT, | ||
137 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), | ||
138 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | | ||
139 | BIT(IIO_CHAN_INFO_INT_TIME), | ||
140 | .scan_index = MAX44000_SCAN_INDEX_ALS, | ||
141 | .scan_type = { | ||
142 | .sign = 'u', | ||
143 | .realbits = 14, | ||
144 | .storagebits = 16, | ||
145 | } | ||
146 | }, | ||
147 | { | ||
148 | .type = IIO_PROXIMITY, | ||
149 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), | ||
150 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), | ||
151 | .scan_index = MAX44000_SCAN_INDEX_PRX, | ||
152 | .scan_type = { | ||
153 | .sign = 'u', | ||
154 | .realbits = 8, | ||
155 | .storagebits = 16, | ||
156 | } | ||
157 | }, | ||
158 | IIO_CHAN_SOFT_TIMESTAMP(2), | ||
159 | { | ||
160 | .type = IIO_CURRENT, | ||
161 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | | ||
162 | BIT(IIO_CHAN_INFO_SCALE), | ||
163 | .extend_name = "led", | ||
164 | .output = 1, | ||
165 | .scan_index = -1, | ||
166 | }, | ||
167 | }; | ||
168 | |||
169 | static int max44000_read_alstim(struct max44000_data *data) | ||
170 | { | ||
171 | unsigned int val; | ||
172 | int ret; | ||
173 | |||
174 | ret = regmap_read(data->regmap, MAX44000_REG_CFG_RX, &val); | ||
175 | if (ret < 0) | ||
176 | return ret; | ||
177 | return (val & MAX44000_CFG_RX_ALSTIM_MASK) >> MAX44000_CFG_RX_ALSTIM_SHIFT; | ||
178 | } | ||
179 | |||
180 | static int max44000_write_alstim(struct max44000_data *data, int val) | ||
181 | { | ||
182 | return regmap_write_bits(data->regmap, MAX44000_REG_CFG_RX, | ||
183 | MAX44000_CFG_RX_ALSTIM_MASK, | ||
184 | val << MAX44000_CFG_RX_ALSTIM_SHIFT); | ||
185 | } | ||
186 | |||
187 | static int max44000_read_alspga(struct max44000_data *data) | ||
188 | { | ||
189 | unsigned int val; | ||
190 | int ret; | ||
191 | |||
192 | ret = regmap_read(data->regmap, MAX44000_REG_CFG_RX, &val); | ||
193 | if (ret < 0) | ||
194 | return ret; | ||
195 | return (val & MAX44000_CFG_RX_ALSPGA_MASK) >> MAX44000_CFG_RX_ALSPGA_SHIFT; | ||
196 | } | ||
197 | |||
198 | static int max44000_write_alspga(struct max44000_data *data, int val) | ||
199 | { | ||
200 | return regmap_write_bits(data->regmap, MAX44000_REG_CFG_RX, | ||
201 | MAX44000_CFG_RX_ALSPGA_MASK, | ||
202 | val << MAX44000_CFG_RX_ALSPGA_SHIFT); | ||
203 | } | ||
204 | |||
205 | static int max44000_read_alsval(struct max44000_data *data) | ||
206 | { | ||
207 | u16 regval; | ||
208 | int alstim, ret; | ||
209 | |||
210 | ret = regmap_bulk_read(data->regmap, MAX44000_REG_ALS_DATA_HI, | ||
211 | ®val, sizeof(regval)); | ||
212 | if (ret < 0) | ||
213 | return ret; | ||
214 | alstim = ret = max44000_read_alstim(data); | ||
215 | if (ret < 0) | ||
216 | return ret; | ||
217 | |||
218 | regval = be16_to_cpu(regval); | ||
219 | |||
220 | /* | ||
221 | * Overflow is explained on datasheet page 17. | ||
222 | * | ||
223 | * It's a warning that either the G or IR channel has become saturated | ||
224 | * and that the value in the register is likely incorrect. | ||
225 | * | ||
226 | * The recommendation is to change the scale (ALSPGA). | ||
227 | * The driver just returns the max representable value. | ||
228 | */ | ||
229 | if (regval & MAX44000_ALSDATA_OVERFLOW) | ||
230 | return 0x3FFF; | ||
231 | |||
232 | return regval << MAX44000_ALSTIM_SHIFT(alstim); | ||
233 | } | ||
234 | |||
235 | static int max44000_write_led_current_raw(struct max44000_data *data, int val) | ||
236 | { | ||
237 | /* Maybe we should clamp the value instead? */ | ||
238 | if (val < 0 || val > MAX44000_LED_CURRENT_MAX) | ||
239 | return -ERANGE; | ||
240 | if (val >= 8) | ||
241 | val += 4; | ||
242 | return regmap_write_bits(data->regmap, MAX44000_REG_CFG_TX, | ||
243 | MAX44000_LED_CURRENT_MASK, val); | ||
244 | } | ||
245 | |||
246 | static int max44000_read_led_current_raw(struct max44000_data *data) | ||
247 | { | ||
248 | unsigned int regval; | ||
249 | int ret; | ||
250 | |||
251 | ret = regmap_read(data->regmap, MAX44000_REG_CFG_TX, ®val); | ||
252 | if (ret < 0) | ||
253 | return ret; | ||
254 | regval &= MAX44000_LED_CURRENT_MASK; | ||
255 | if (regval >= 8) | ||
256 | regval -= 4; | ||
257 | return regval; | ||
258 | } | ||
259 | |||
260 | static int max44000_read_raw(struct iio_dev *indio_dev, | ||
261 | struct iio_chan_spec const *chan, | ||
262 | int *val, int *val2, long mask) | ||
263 | { | ||
264 | struct max44000_data *data = iio_priv(indio_dev); | ||
265 | int alstim, alspga; | ||
266 | unsigned int regval; | ||
267 | int ret; | ||
268 | |||
269 | switch (mask) { | ||
270 | case IIO_CHAN_INFO_RAW: | ||
271 | switch (chan->type) { | ||
272 | case IIO_LIGHT: | ||
273 | mutex_lock(&data->lock); | ||
274 | ret = max44000_read_alsval(data); | ||
275 | mutex_unlock(&data->lock); | ||
276 | if (ret < 0) | ||
277 | return ret; | ||
278 | *val = ret; | ||
279 | return IIO_VAL_INT; | ||
280 | |||
281 | case IIO_PROXIMITY: | ||
282 | mutex_lock(&data->lock); | ||
283 | ret = regmap_read(data->regmap, MAX44000_REG_PRX_DATA, ®val); | ||
284 | mutex_unlock(&data->lock); | ||
285 | if (ret < 0) | ||
286 | return ret; | ||
287 | *val = regval; | ||
288 | return IIO_VAL_INT; | ||
289 | |||
290 | case IIO_CURRENT: | ||
291 | mutex_lock(&data->lock); | ||
292 | ret = max44000_read_led_current_raw(data); | ||
293 | mutex_unlock(&data->lock); | ||
294 | if (ret < 0) | ||
295 | return ret; | ||
296 | *val = ret; | ||
297 | return IIO_VAL_INT; | ||
298 | |||
299 | default: | ||
300 | return -EINVAL; | ||
301 | } | ||
302 | |||
303 | case IIO_CHAN_INFO_SCALE: | ||
304 | switch (chan->type) { | ||
305 | case IIO_CURRENT: | ||
306 | /* Output register is in 10s of miliamps */ | ||
307 | *val = 10; | ||
308 | return IIO_VAL_INT; | ||
309 | |||
310 | case IIO_LIGHT: | ||
311 | mutex_lock(&data->lock); | ||
312 | alspga = ret = max44000_read_alspga(data); | ||
313 | mutex_unlock(&data->lock); | ||
314 | if (ret < 0) | ||
315 | return ret; | ||
316 | |||
317 | /* Avoid negative shifts */ | ||
318 | *val = (1 << MAX44000_ALSPGA_MAX_SHIFT); | ||
319 | *val2 = MAX44000_ALS_TO_LUX_DEFAULT_FRACTION_LOG2 | ||
320 | + MAX44000_ALSPGA_MAX_SHIFT | ||
321 | - max44000_alspga_shift[alspga]; | ||
322 | return IIO_VAL_FRACTIONAL_LOG2; | ||
323 | |||
324 | default: | ||
325 | return -EINVAL; | ||
326 | } | ||
327 | |||
328 | case IIO_CHAN_INFO_INT_TIME: | ||
329 | mutex_lock(&data->lock); | ||
330 | alstim = ret = max44000_read_alstim(data); | ||
331 | mutex_unlock(&data->lock); | ||
332 | |||
333 | if (ret < 0) | ||
334 | return ret; | ||
335 | *val = 0; | ||
336 | *val2 = max44000_int_time_avail_ns_array[alstim]; | ||
337 | return IIO_VAL_INT_PLUS_NANO; | ||
338 | |||
339 | default: | ||
340 | return -EINVAL; | ||
341 | } | ||
342 | } | ||
343 | |||
344 | static int max44000_write_raw(struct iio_dev *indio_dev, | ||
345 | struct iio_chan_spec const *chan, | ||
346 | int val, int val2, long mask) | ||
347 | { | ||
348 | struct max44000_data *data = iio_priv(indio_dev); | ||
349 | int ret; | ||
350 | |||
351 | if (mask == IIO_CHAN_INFO_RAW && chan->type == IIO_CURRENT) { | ||
352 | mutex_lock(&data->lock); | ||
353 | ret = max44000_write_led_current_raw(data, val); | ||
354 | mutex_unlock(&data->lock); | ||
355 | return ret; | ||
356 | } else if (mask == IIO_CHAN_INFO_INT_TIME && chan->type == IIO_LIGHT) { | ||
357 | s64 valns = val * NSEC_PER_SEC + val2; | ||
358 | int alstim = find_closest_descending(valns, | ||
359 | max44000_int_time_avail_ns_array, | ||
360 | ARRAY_SIZE(max44000_int_time_avail_ns_array)); | ||
361 | mutex_lock(&data->lock); | ||
362 | ret = max44000_write_alstim(data, alstim); | ||
363 | mutex_unlock(&data->lock); | ||
364 | return ret; | ||
365 | } else if (mask == IIO_CHAN_INFO_SCALE && chan->type == IIO_LIGHT) { | ||
366 | s64 valus = val * USEC_PER_SEC + val2; | ||
367 | int alspga = find_closest(valus, | ||
368 | max44000_scale_avail_ulux_array, | ||
369 | ARRAY_SIZE(max44000_scale_avail_ulux_array)); | ||
370 | mutex_lock(&data->lock); | ||
371 | ret = max44000_write_alspga(data, alspga); | ||
372 | mutex_unlock(&data->lock); | ||
373 | return ret; | ||
374 | } | ||
375 | |||
376 | return -EINVAL; | ||
377 | } | ||
378 | |||
379 | static int max44000_write_raw_get_fmt(struct iio_dev *indio_dev, | ||
380 | struct iio_chan_spec const *chan, | ||
381 | long mask) | ||
382 | { | ||
383 | if (mask == IIO_CHAN_INFO_INT_TIME && chan->type == IIO_LIGHT) | ||
384 | return IIO_VAL_INT_PLUS_NANO; | ||
385 | else if (mask == IIO_CHAN_INFO_SCALE && chan->type == IIO_LIGHT) | ||
386 | return IIO_VAL_INT_PLUS_MICRO; | ||
387 | else | ||
388 | return IIO_VAL_INT; | ||
389 | } | ||
390 | |||
391 | static IIO_CONST_ATTR(illuminance_integration_time_available, max44000_int_time_avail_str); | ||
392 | static IIO_CONST_ATTR(illuminance_scale_available, max44000_scale_avail_str); | ||
393 | |||
394 | static struct attribute *max44000_attributes[] = { | ||
395 | &iio_const_attr_illuminance_integration_time_available.dev_attr.attr, | ||
396 | &iio_const_attr_illuminance_scale_available.dev_attr.attr, | ||
397 | NULL | ||
398 | }; | ||
399 | |||
400 | static const struct attribute_group max44000_attribute_group = { | ||
401 | .attrs = max44000_attributes, | ||
402 | }; | ||
403 | |||
404 | static const struct iio_info max44000_info = { | ||
405 | .driver_module = THIS_MODULE, | ||
406 | .read_raw = max44000_read_raw, | ||
407 | .write_raw = max44000_write_raw, | ||
408 | .write_raw_get_fmt = max44000_write_raw_get_fmt, | ||
409 | .attrs = &max44000_attribute_group, | ||
410 | }; | ||
411 | |||
412 | static bool max44000_readable_reg(struct device *dev, unsigned int reg) | ||
413 | { | ||
414 | switch (reg) { | ||
415 | case MAX44000_REG_STATUS: | ||
416 | case MAX44000_REG_CFG_MAIN: | ||
417 | case MAX44000_REG_CFG_RX: | ||
418 | case MAX44000_REG_CFG_TX: | ||
419 | case MAX44000_REG_ALS_DATA_HI: | ||
420 | case MAX44000_REG_ALS_DATA_LO: | ||
421 | case MAX44000_REG_PRX_DATA: | ||
422 | case MAX44000_REG_ALS_UPTHR_HI: | ||
423 | case MAX44000_REG_ALS_UPTHR_LO: | ||
424 | case MAX44000_REG_ALS_LOTHR_HI: | ||
425 | case MAX44000_REG_ALS_LOTHR_LO: | ||
426 | case MAX44000_REG_PST: | ||
427 | case MAX44000_REG_PRX_IND: | ||
428 | case MAX44000_REG_PRX_THR: | ||
429 | case MAX44000_REG_TRIM_GAIN_GREEN: | ||
430 | case MAX44000_REG_TRIM_GAIN_IR: | ||
431 | return true; | ||
432 | default: | ||
433 | return false; | ||
434 | } | ||
435 | } | ||
436 | |||
437 | static bool max44000_writeable_reg(struct device *dev, unsigned int reg) | ||
438 | { | ||
439 | switch (reg) { | ||
440 | case MAX44000_REG_CFG_MAIN: | ||
441 | case MAX44000_REG_CFG_RX: | ||
442 | case MAX44000_REG_CFG_TX: | ||
443 | case MAX44000_REG_ALS_UPTHR_HI: | ||
444 | case MAX44000_REG_ALS_UPTHR_LO: | ||
445 | case MAX44000_REG_ALS_LOTHR_HI: | ||
446 | case MAX44000_REG_ALS_LOTHR_LO: | ||
447 | case MAX44000_REG_PST: | ||
448 | case MAX44000_REG_PRX_IND: | ||
449 | case MAX44000_REG_PRX_THR: | ||
450 | case MAX44000_REG_TRIM_GAIN_GREEN: | ||
451 | case MAX44000_REG_TRIM_GAIN_IR: | ||
452 | return true; | ||
453 | default: | ||
454 | return false; | ||
455 | } | ||
456 | } | ||
457 | |||
458 | static bool max44000_volatile_reg(struct device *dev, unsigned int reg) | ||
459 | { | ||
460 | switch (reg) { | ||
461 | case MAX44000_REG_STATUS: | ||
462 | case MAX44000_REG_ALS_DATA_HI: | ||
463 | case MAX44000_REG_ALS_DATA_LO: | ||
464 | case MAX44000_REG_PRX_DATA: | ||
465 | return true; | ||
466 | default: | ||
467 | return false; | ||
468 | } | ||
469 | } | ||
470 | |||
471 | static bool max44000_precious_reg(struct device *dev, unsigned int reg) | ||
472 | { | ||
473 | return reg == MAX44000_REG_STATUS; | ||
474 | } | ||
475 | |||
476 | static const struct regmap_config max44000_regmap_config = { | ||
477 | .reg_bits = 8, | ||
478 | .val_bits = 8, | ||
479 | |||
480 | .max_register = MAX44000_REG_PRX_DATA, | ||
481 | .readable_reg = max44000_readable_reg, | ||
482 | .writeable_reg = max44000_writeable_reg, | ||
483 | .volatile_reg = max44000_volatile_reg, | ||
484 | .precious_reg = max44000_precious_reg, | ||
485 | |||
486 | .use_single_rw = 1, | ||
487 | .cache_type = REGCACHE_RBTREE, | ||
488 | }; | ||
489 | |||
490 | static irqreturn_t max44000_trigger_handler(int irq, void *p) | ||
491 | { | ||
492 | struct iio_poll_func *pf = p; | ||
493 | struct iio_dev *indio_dev = pf->indio_dev; | ||
494 | struct max44000_data *data = iio_priv(indio_dev); | ||
495 | u16 buf[8]; /* 2x u16 + padding + 8 bytes timestamp */ | ||
496 | int index = 0; | ||
497 | unsigned int regval; | ||
498 | int ret; | ||
499 | |||
500 | mutex_lock(&data->lock); | ||
501 | if (test_bit(MAX44000_SCAN_INDEX_ALS, indio_dev->active_scan_mask)) { | ||
502 | ret = max44000_read_alsval(data); | ||
503 | if (ret < 0) | ||
504 | goto out_unlock; | ||
505 | buf[index++] = ret; | ||
506 | } | ||
507 | if (test_bit(MAX44000_SCAN_INDEX_PRX, indio_dev->active_scan_mask)) { | ||
508 | ret = regmap_read(data->regmap, MAX44000_REG_PRX_DATA, ®val); | ||
509 | if (ret < 0) | ||
510 | goto out_unlock; | ||
511 | buf[index] = regval; | ||
512 | } | ||
513 | mutex_unlock(&data->lock); | ||
514 | |||
515 | iio_push_to_buffers_with_timestamp(indio_dev, buf, iio_get_time_ns()); | ||
516 | iio_trigger_notify_done(indio_dev->trig); | ||
517 | return IRQ_HANDLED; | ||
518 | |||
519 | out_unlock: | ||
520 | mutex_unlock(&data->lock); | ||
521 | iio_trigger_notify_done(indio_dev->trig); | ||
522 | return IRQ_HANDLED; | ||
523 | } | ||
524 | |||
525 | static int max44000_probe(struct i2c_client *client, | ||
526 | const struct i2c_device_id *id) | ||
527 | { | ||
528 | struct max44000_data *data; | ||
529 | struct iio_dev *indio_dev; | ||
530 | int ret, reg; | ||
531 | |||
532 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); | ||
533 | if (!indio_dev) | ||
534 | return -ENOMEM; | ||
535 | data = iio_priv(indio_dev); | ||
536 | data->regmap = devm_regmap_init_i2c(client, &max44000_regmap_config); | ||
537 | if (IS_ERR(data->regmap)) { | ||
538 | dev_err(&client->dev, "regmap_init failed!\n"); | ||
539 | return PTR_ERR(data->regmap); | ||
540 | } | ||
541 | |||
542 | i2c_set_clientdata(client, indio_dev); | ||
543 | mutex_init(&data->lock); | ||
544 | indio_dev->dev.parent = &client->dev; | ||
545 | indio_dev->info = &max44000_info; | ||
546 | indio_dev->name = MAX44000_DRV_NAME; | ||
547 | indio_dev->channels = max44000_channels; | ||
548 | indio_dev->num_channels = ARRAY_SIZE(max44000_channels); | ||
549 | |||
550 | /* | ||
551 | * The device doesn't have a reset function so we just clear some | ||
552 | * important bits at probe time to ensure sane operation. | ||
553 | * | ||
554 | * Since we don't support interrupts/events the threshold values are | ||
555 | * not important. We also don't touch trim values. | ||
556 | */ | ||
557 | |||
558 | /* Reset ALS scaling bits */ | ||
559 | ret = regmap_write(data->regmap, MAX44000_REG_CFG_RX, | ||
560 | MAX44000_REG_CFG_RX_DEFAULT); | ||
561 | if (ret < 0) { | ||
562 | dev_err(&client->dev, "failed to write default CFG_RX: %d\n", | ||
563 | ret); | ||
564 | return ret; | ||
565 | } | ||
566 | |||
567 | /* | ||
568 | * By default the LED pulse used for the proximity sensor is disabled. | ||
569 | * Set a middle value so that we get some sort of valid data by default. | ||
570 | */ | ||
571 | ret = max44000_write_led_current_raw(data, MAX44000_LED_CURRENT_DEFAULT); | ||
572 | if (ret < 0) { | ||
573 | dev_err(&client->dev, "failed to write init config: %d\n", ret); | ||
574 | return ret; | ||
575 | } | ||
576 | |||
577 | /* Reset CFG bits to ALS_PRX mode which allows easy reading of both values. */ | ||
578 | reg = MAX44000_CFG_TRIM | MAX44000_CFG_MODE_ALS_PRX; | ||
579 | ret = regmap_write(data->regmap, MAX44000_REG_CFG_MAIN, reg); | ||
580 | if (ret < 0) { | ||
581 | dev_err(&client->dev, "failed to write init config: %d\n", ret); | ||
582 | return ret; | ||
583 | } | ||
584 | |||
585 | /* Read status at least once to clear any stale interrupt bits. */ | ||
586 | ret = regmap_read(data->regmap, MAX44000_REG_STATUS, ®); | ||
587 | if (ret < 0) { | ||
588 | dev_err(&client->dev, "failed to read init status: %d\n", ret); | ||
589 | return ret; | ||
590 | } | ||
591 | |||
592 | ret = iio_triggered_buffer_setup(indio_dev, NULL, max44000_trigger_handler, NULL); | ||
593 | if (ret < 0) { | ||
594 | dev_err(&client->dev, "iio triggered buffer setup failed\n"); | ||
595 | return ret; | ||
596 | } | ||
597 | |||
598 | return iio_device_register(indio_dev); | ||
599 | } | ||
600 | |||
601 | static int max44000_remove(struct i2c_client *client) | ||
602 | { | ||
603 | struct iio_dev *indio_dev = i2c_get_clientdata(client); | ||
604 | |||
605 | iio_device_unregister(indio_dev); | ||
606 | iio_triggered_buffer_cleanup(indio_dev); | ||
607 | |||
608 | return 0; | ||
609 | } | ||
610 | |||
611 | static const struct i2c_device_id max44000_id[] = { | ||
612 | {"max44000", 0}, | ||
613 | { } | ||
614 | }; | ||
615 | MODULE_DEVICE_TABLE(i2c, max44000_id); | ||
616 | |||
617 | #ifdef CONFIG_ACPI | ||
618 | static const struct acpi_device_id max44000_acpi_match[] = { | ||
619 | {"MAX44000", 0}, | ||
620 | { } | ||
621 | }; | ||
622 | MODULE_DEVICE_TABLE(acpi, max44000_acpi_match); | ||
623 | #endif | ||
624 | |||
625 | static struct i2c_driver max44000_driver = { | ||
626 | .driver = { | ||
627 | .name = MAX44000_DRV_NAME, | ||
628 | .acpi_match_table = ACPI_PTR(max44000_acpi_match), | ||
629 | }, | ||
630 | .probe = max44000_probe, | ||
631 | .remove = max44000_remove, | ||
632 | .id_table = max44000_id, | ||
633 | }; | ||
634 | |||
635 | module_i2c_driver(max44000_driver); | ||
636 | |||
637 | MODULE_AUTHOR("Crestez Dan Leonard <leonard.crestez@intel.com>"); | ||
638 | MODULE_DESCRIPTION("MAX44000 Ambient and Infrared Proximity Sensor"); | ||
639 | MODULE_LICENSE("GPL v2"); | ||