1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * vcnl4000.c - Support for Vishay VCNL4000/4010/4020/4040/4200 combined ambient
4 * light and proximity sensor
5 *
6 * Copyright 2012 Peter Meerwald <pmeerw@pmeerw.net>
7 * Copyright 2019 Pursim SPC
8 * Copyright 2020 Mathieu Othacehe <m.othacehe@gmail.com>
9 *
10 * IIO driver for:
11 * VCNL4000/10/20 (7-bit I2C slave address 0x13)
12 * VCNL4040 (7-bit I2C slave address 0x60)
13 * VCNL4200 (7-bit I2C slave address 0x51)
14 *
15 * TODO:
16 * allow to adjust IR current
17 * interrupts (VCNL4040, VCNL4200)
18 */
19
20 #include <linux/bitfield.h>
21 #include <linux/module.h>
22 #include <linux/i2c.h>
23 #include <linux/err.h>
24 #include <linux/delay.h>
25 #include <linux/pm_runtime.h>
26 #include <linux/interrupt.h>
27 #include <linux/units.h>
28
29 #include <linux/iio/buffer.h>
30 #include <linux/iio/events.h>
31 #include <linux/iio/iio.h>
32 #include <linux/iio/sysfs.h>
33 #include <linux/iio/trigger.h>
34 #include <linux/iio/trigger_consumer.h>
35 #include <linux/iio/triggered_buffer.h>
36
37 #define VCNL4000_DRV_NAME "vcnl4000"
38 #define VCNL4000_PROD_ID 0x01
39 #define VCNL4010_PROD_ID 0x02 /* for VCNL4020, VCNL4010 */
40 #define VCNL4040_PROD_ID 0x86
41 #define VCNL4200_PROD_ID 0x58
42
43 #define VCNL4000_COMMAND 0x80 /* Command register */
44 #define VCNL4000_PROD_REV 0x81 /* Product ID and Revision ID */
45 #define VCNL4010_PROX_RATE 0x82 /* Proximity rate */
46 #define VCNL4000_LED_CURRENT 0x83 /* IR LED current for proximity mode */
47 #define VCNL4000_AL_PARAM 0x84 /* Ambient light parameter register */
48 #define VCNL4010_ALS_PARAM 0x84 /* ALS rate */
49 #define VCNL4000_AL_RESULT_HI 0x85 /* Ambient light result register, MSB */
50 #define VCNL4000_AL_RESULT_LO 0x86 /* Ambient light result register, LSB */
51 #define VCNL4000_PS_RESULT_HI 0x87 /* Proximity result register, MSB */
52 #define VCNL4000_PS_RESULT_LO 0x88 /* Proximity result register, LSB */
53 #define VCNL4000_PS_MEAS_FREQ 0x89 /* Proximity test signal frequency */
54 #define VCNL4010_INT_CTRL 0x89 /* Interrupt control */
55 #define VCNL4000_PS_MOD_ADJ 0x8a /* Proximity modulator timing adjustment */
56 #define VCNL4010_LOW_THR_HI 0x8a /* Low threshold, MSB */
57 #define VCNL4010_LOW_THR_LO 0x8b /* Low threshold, LSB */
58 #define VCNL4010_HIGH_THR_HI 0x8c /* High threshold, MSB */
59 #define VCNL4010_HIGH_THR_LO 0x8d /* High threshold, LSB */
60 #define VCNL4010_ISR 0x8e /* Interrupt status */
61
62 #define VCNL4200_AL_CONF 0x00 /* Ambient light configuration */
63 #define VCNL4200_PS_CONF1 0x03 /* Proximity configuration */
64 #define VCNL4200_PS_CONF3 0x04 /* Proximity configuration */
65 #define VCNL4040_PS_THDL_LM 0x06 /* Proximity threshold low */
66 #define VCNL4040_PS_THDH_LM 0x07 /* Proximity threshold high */
67 #define VCNL4040_ALS_THDL_LM 0x02 /* Ambient light threshold low */
68 #define VCNL4040_ALS_THDH_LM 0x01 /* Ambient light threshold high */
69 #define VCNL4200_PS_DATA 0x08 /* Proximity data */
70 #define VCNL4200_AL_DATA 0x09 /* Ambient light data */
71 #define VCNL4040_INT_FLAGS 0x0b /* Interrupt register */
72 #define VCNL4200_INT_FLAGS 0x0d /* Interrupt register */
73 #define VCNL4200_DEV_ID 0x0e /* Device ID, slave address and version */
74
75 #define VCNL4040_DEV_ID 0x0c /* Device ID and version */
76
77 /* Bit masks for COMMAND register */
78 #define VCNL4000_AL_RDY BIT(6) /* ALS data ready? */
79 #define VCNL4000_PS_RDY BIT(5) /* proximity data ready? */
80 #define VCNL4000_AL_OD BIT(4) /* start on-demand ALS measurement */
81 #define VCNL4000_PS_OD BIT(3) /* start on-demand proximity measurement */
82 #define VCNL4000_ALS_EN BIT(2) /* start ALS measurement */
83 #define VCNL4000_PROX_EN BIT(1) /* start proximity measurement */
84 #define VCNL4000_SELF_TIMED_EN BIT(0) /* start self-timed measurement */
85
86 #define VCNL4040_ALS_CONF_ALS_SHUTDOWN BIT(0)
87 #define VCNL4040_ALS_CONF_IT GENMASK(7, 6) /* Ambient integration time */
88 #define VCNL4040_ALS_CONF_INT_EN BIT(1) /* Ambient light Interrupt enable */
89 #define VCNL4040_ALS_CONF_PERS GENMASK(3, 2) /* Ambient interrupt persistence setting */
90 #define VCNL4040_PS_CONF1_PS_SHUTDOWN BIT(0)
91 #define VCNL4040_PS_CONF2_PS_IT GENMASK(3, 1) /* Proximity integration time */
92 #define VCNL4040_CONF1_PS_PERS GENMASK(5, 4) /* Proximity interrupt persistence setting */
93 #define VCNL4040_PS_CONF2_PS_HD BIT(11) /* Proximity high definition */
94 #define VCNL4040_PS_CONF2_PS_INT GENMASK(9, 8) /* Proximity interrupt mode */
95 #define VCNL4040_PS_CONF3_MPS GENMASK(6, 5) /* Proximity multi pulse number */
96 #define VCNL4040_PS_MS_LED_I GENMASK(10, 8) /* Proximity current */
97 #define VCNL4040_PS_IF_AWAY BIT(8) /* Proximity event cross low threshold */
98 #define VCNL4040_PS_IF_CLOSE BIT(9) /* Proximity event cross high threshold */
99 #define VCNL4040_ALS_RISING BIT(12) /* Ambient Light cross high threshold */
100 #define VCNL4040_ALS_FALLING BIT(13) /* Ambient Light cross low threshold */
101
102 /* Bit masks for interrupt registers. */
103 #define VCNL4010_INT_THR_SEL BIT(0) /* Select threshold interrupt source */
104 #define VCNL4010_INT_THR_EN BIT(1) /* Threshold interrupt type */
105 #define VCNL4010_INT_ALS_EN BIT(2) /* Enable on ALS data ready */
106 #define VCNL4010_INT_PROX_EN BIT(3) /* Enable on proximity data ready */
107
108 #define VCNL4010_INT_THR_HIGH 0 /* High threshold exceeded */
109 #define VCNL4010_INT_THR_LOW 1 /* Low threshold exceeded */
110 #define VCNL4010_INT_ALS 2 /* ALS data ready */
111 #define VCNL4010_INT_PROXIMITY 3 /* Proximity data ready */
112
113 #define VCNL4010_INT_THR \
114 (BIT(VCNL4010_INT_THR_LOW) | BIT(VCNL4010_INT_THR_HIGH))
115 #define VCNL4010_INT_DRDY \
116 (BIT(VCNL4010_INT_PROXIMITY) | BIT(VCNL4010_INT_ALS))
117
118 #define VCNL4040_CONF3_PS_MPS_16BITS 3 /* 8 multi pulses */
119 #define VCNL4040_CONF3_PS_LED_I_16BITS 3 /* 120 mA */
120
121 #define VCNL4040_CONF3_PS_SAMPLE_16BITS \
122 (FIELD_PREP(VCNL4040_PS_CONF3_MPS, VCNL4040_CONF3_PS_MPS_16BITS) | \
123 FIELD_PREP(VCNL4040_PS_MS_LED_I, VCNL4040_CONF3_PS_LED_I_16BITS))
124
125 static const int vcnl4010_prox_sampling_frequency[][2] = {
126 {1, 950000},
127 {3, 906250},
128 {7, 812500},
129 {16, 625000},
130 {31, 250000},
131 {62, 500000},
132 {125, 0},
133 {250, 0},
134 };
135
136 static const int vcnl4040_ps_it_times[][2] = {
137 {0, 100},
138 {0, 150},
139 {0, 200},
140 {0, 250},
141 {0, 300},
142 {0, 350},
143 {0, 400},
144 {0, 800},
145 };
146
147 static const int vcnl4200_ps_it_times[][2] = {
148 {0, 96},
149 {0, 144},
150 {0, 192},
151 {0, 384},
152 {0, 768},
153 {0, 864},
154 };
155
156 static const int vcnl4040_als_it_times[][2] = {
157 {0, 80000},
158 {0, 160000},
159 {0, 320000},
160 {0, 640000},
161 };
162
163 static const int vcnl4200_als_it_times[][2] = {
164 {0, 50000},
165 {0, 100000},
166 {0, 200000},
167 {0, 400000},
168 };
169
170 static const int vcnl4040_ps_calibbias_ua[][2] = {
171 {0, 50000},
172 {0, 75000},
173 {0, 100000},
174 {0, 120000},
175 {0, 140000},
176 {0, 160000},
177 {0, 180000},
178 {0, 200000},
179 };
180
181 static const int vcnl4040_als_persistence[] = {1, 2, 4, 8};
182 static const int vcnl4040_ps_persistence[] = {1, 2, 3, 4};
183 static const int vcnl4040_ps_oversampling_ratio[] = {1, 2, 4, 8};
184
185 #define VCNL4000_SLEEP_DELAY_MS 2000 /* before we enter pm_runtime_suspend */
186
187 enum vcnl4000_device_ids {
188 VCNL4000,
189 VCNL4010,
190 VCNL4040,
191 VCNL4200,
192 };
193
194 struct vcnl4200_channel {
195 u8 reg;
196 ktime_t last_measurement;
197 ktime_t sampling_rate;
198 struct mutex lock;
199 };
200
201 struct vcnl4000_data {
202 struct i2c_client *client;
203 enum vcnl4000_device_ids id;
204 int rev;
205 int al_scale;
206 int ps_scale;
207 u8 ps_int; /* proximity interrupt mode */
208 u8 als_int; /* ambient light interrupt mode*/
209 const struct vcnl4000_chip_spec *chip_spec;
210 struct mutex vcnl4000_lock;
211 struct vcnl4200_channel vcnl4200_al;
212 struct vcnl4200_channel vcnl4200_ps;
213 uint32_t near_level;
214 };
215
216 struct vcnl4000_chip_spec {
217 const char *prod;
218 struct iio_chan_spec const *channels;
219 const int num_channels;
220 const struct iio_info *info;
221 const struct iio_buffer_setup_ops *buffer_setup_ops;
222 int (*init)(struct vcnl4000_data *data);
223 int (*measure_light)(struct vcnl4000_data *data, int *val);
224 int (*measure_proximity)(struct vcnl4000_data *data, int *val);
225 int (*set_power_state)(struct vcnl4000_data *data, bool on);
226 irqreturn_t (*irq_thread)(int irq, void *priv);
227 irqreturn_t (*trig_buffer_func)(int irq, void *priv);
228
229 u8 int_reg;
230 const int(*ps_it_times)[][2];
231 const int num_ps_it_times;
232 const int(*als_it_times)[][2];
233 const int num_als_it_times;
234 const unsigned int ulux_step;
235 };
236
237 static const struct i2c_device_id vcnl4000_id[] = {
238 { "vcnl4000", VCNL4000 },
239 { "vcnl4010", VCNL4010 },
240 { "vcnl4020", VCNL4010 },
241 { "vcnl4040", VCNL4040 },
242 { "vcnl4200", VCNL4200 },
243 { }
244 };
245 MODULE_DEVICE_TABLE(i2c, vcnl4000_id);
246
vcnl4000_set_power_state(struct vcnl4000_data * data,bool on)247 static int vcnl4000_set_power_state(struct vcnl4000_data *data, bool on)
248 {
249 /* no suspend op */
250 return 0;
251 }
252
vcnl4000_init(struct vcnl4000_data * data)253 static int vcnl4000_init(struct vcnl4000_data *data)
254 {
255 int ret, prod_id;
256
257 ret = i2c_smbus_read_byte_data(data->client, VCNL4000_PROD_REV);
258 if (ret < 0)
259 return ret;
260
261 prod_id = ret >> 4;
262 switch (prod_id) {
263 case VCNL4000_PROD_ID:
264 if (data->id != VCNL4000)
265 dev_warn(&data->client->dev,
266 "wrong device id, use vcnl4000");
267 break;
268 case VCNL4010_PROD_ID:
269 if (data->id != VCNL4010)
270 dev_warn(&data->client->dev,
271 "wrong device id, use vcnl4010/4020");
272 break;
273 default:
274 return -ENODEV;
275 }
276
277 data->rev = ret & 0xf;
278 data->al_scale = 250000;
279
280 return data->chip_spec->set_power_state(data, true);
281 };
282
vcnl4000_write_als_enable(struct vcnl4000_data * data,bool en)283 static ssize_t vcnl4000_write_als_enable(struct vcnl4000_data *data, bool en)
284 {
285 int ret;
286
287 mutex_lock(&data->vcnl4000_lock);
288
289 ret = i2c_smbus_read_word_data(data->client, VCNL4200_AL_CONF);
290 if (ret < 0)
291 goto out;
292
293 if (en)
294 ret &= ~VCNL4040_ALS_CONF_ALS_SHUTDOWN;
295 else
296 ret |= VCNL4040_ALS_CONF_ALS_SHUTDOWN;
297
298 ret = i2c_smbus_write_word_data(data->client, VCNL4200_AL_CONF, ret);
299
300 out:
301 mutex_unlock(&data->vcnl4000_lock);
302
303 return ret;
304 }
305
vcnl4000_write_ps_enable(struct vcnl4000_data * data,bool en)306 static ssize_t vcnl4000_write_ps_enable(struct vcnl4000_data *data, bool en)
307 {
308 int ret;
309
310 mutex_lock(&data->vcnl4000_lock);
311
312 ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1);
313 if (ret < 0)
314 goto out;
315
316 if (en)
317 ret &= ~VCNL4040_PS_CONF1_PS_SHUTDOWN;
318 else
319 ret |= VCNL4040_PS_CONF1_PS_SHUTDOWN;
320
321 ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF1, ret);
322
323 out:
324 mutex_unlock(&data->vcnl4000_lock);
325
326 return ret;
327 }
328
vcnl4200_set_power_state(struct vcnl4000_data * data,bool on)329 static int vcnl4200_set_power_state(struct vcnl4000_data *data, bool on)
330 {
331 int ret;
332
333 /* Do not power down if interrupts are enabled */
334 if (!on && (data->ps_int || data->als_int))
335 return 0;
336
337 ret = vcnl4000_write_als_enable(data, on);
338 if (ret < 0)
339 return ret;
340
341 ret = vcnl4000_write_ps_enable(data, on);
342 if (ret < 0)
343 return ret;
344
345 if (on) {
346 /* Wait at least one integration cycle before fetching data */
347 data->vcnl4200_al.last_measurement = ktime_get();
348 data->vcnl4200_ps.last_measurement = ktime_get();
349 }
350
351 return 0;
352 }
353
vcnl4200_init(struct vcnl4000_data * data)354 static int vcnl4200_init(struct vcnl4000_data *data)
355 {
356 int ret, id;
357 u16 regval;
358
359 ret = i2c_smbus_read_word_data(data->client, VCNL4200_DEV_ID);
360 if (ret < 0)
361 return ret;
362
363 id = ret & 0xff;
364
365 if (id != VCNL4200_PROD_ID) {
366 ret = i2c_smbus_read_word_data(data->client, VCNL4040_DEV_ID);
367 if (ret < 0)
368 return ret;
369
370 id = ret & 0xff;
371
372 if (id != VCNL4040_PROD_ID)
373 return -ENODEV;
374 }
375
376 dev_dbg(&data->client->dev, "device id 0x%x", id);
377
378 data->rev = (ret >> 8) & 0xf;
379 data->ps_int = 0;
380 data->als_int = 0;
381
382 data->vcnl4200_al.reg = VCNL4200_AL_DATA;
383 data->vcnl4200_ps.reg = VCNL4200_PS_DATA;
384 switch (id) {
385 case VCNL4200_PROD_ID:
386 /* Default wait time is 50ms, add 20% tolerance. */
387 data->vcnl4200_al.sampling_rate = ktime_set(0, 60000 * 1000);
388 /* Default wait time is 4.8ms, add 20% tolerance. */
389 data->vcnl4200_ps.sampling_rate = ktime_set(0, 5760 * 1000);
390 break;
391 case VCNL4040_PROD_ID:
392 /* Default wait time is 80ms, add 20% tolerance. */
393 data->vcnl4200_al.sampling_rate = ktime_set(0, 96000 * 1000);
394 /* Default wait time is 5ms, add 20% tolerance. */
395 data->vcnl4200_ps.sampling_rate = ktime_set(0, 6000 * 1000);
396 break;
397 }
398 data->al_scale = data->chip_spec->ulux_step;
399 data->ps_scale = 16;
400 mutex_init(&data->vcnl4200_al.lock);
401 mutex_init(&data->vcnl4200_ps.lock);
402
403 /* Use 16 bits proximity sensor readings */
404 ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1);
405 if (ret < 0)
406 return ret;
407
408 regval = ret | VCNL4040_PS_CONF2_PS_HD;
409 ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF1,
410 regval);
411 if (ret < 0)
412 return ret;
413
414 /* Align proximity sensor sample rate to 16 bits data width */
415 ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF3);
416 if (ret < 0)
417 return ret;
418
419 regval = ret | VCNL4040_CONF3_PS_SAMPLE_16BITS;
420 ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF3,
421 regval);
422 if (ret < 0)
423 return ret;
424
425 ret = data->chip_spec->set_power_state(data, true);
426 if (ret < 0)
427 return ret;
428
429 return 0;
430 };
431
vcnl4000_read_data(struct vcnl4000_data * data,u8 data_reg,int * val)432 static int vcnl4000_read_data(struct vcnl4000_data *data, u8 data_reg, int *val)
433 {
434 s32 ret;
435
436 ret = i2c_smbus_read_word_swapped(data->client, data_reg);
437 if (ret < 0)
438 return ret;
439
440 *val = ret;
441 return 0;
442 }
443
vcnl4000_write_data(struct vcnl4000_data * data,u8 data_reg,int val)444 static int vcnl4000_write_data(struct vcnl4000_data *data, u8 data_reg, int val)
445 {
446 if (val > U16_MAX)
447 return -ERANGE;
448
449 return i2c_smbus_write_word_swapped(data->client, data_reg, val);
450 }
451
452
vcnl4000_measure(struct vcnl4000_data * data,u8 req_mask,u8 rdy_mask,u8 data_reg,int * val)453 static int vcnl4000_measure(struct vcnl4000_data *data, u8 req_mask,
454 u8 rdy_mask, u8 data_reg, int *val)
455 {
456 int tries = 20;
457 int ret;
458
459 mutex_lock(&data->vcnl4000_lock);
460
461 ret = i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND,
462 req_mask);
463 if (ret < 0)
464 goto fail;
465
466 /* wait for data to become ready */
467 while (tries--) {
468 ret = i2c_smbus_read_byte_data(data->client, VCNL4000_COMMAND);
469 if (ret < 0)
470 goto fail;
471 if (ret & rdy_mask)
472 break;
473 msleep(20); /* measurement takes up to 100 ms */
474 }
475
476 if (tries < 0) {
477 dev_err(&data->client->dev,
478 "vcnl4000_measure() failed, data not ready\n");
479 ret = -EIO;
480 goto fail;
481 }
482
483 ret = vcnl4000_read_data(data, data_reg, val);
484 if (ret < 0)
485 goto fail;
486
487 mutex_unlock(&data->vcnl4000_lock);
488
489 return 0;
490
491 fail:
492 mutex_unlock(&data->vcnl4000_lock);
493 return ret;
494 }
495
vcnl4200_measure(struct vcnl4000_data * data,struct vcnl4200_channel * chan,int * val)496 static int vcnl4200_measure(struct vcnl4000_data *data,
497 struct vcnl4200_channel *chan, int *val)
498 {
499 int ret;
500 s64 delta;
501 ktime_t next_measurement;
502
503 mutex_lock(&chan->lock);
504
505 next_measurement = ktime_add(chan->last_measurement,
506 chan->sampling_rate);
507 delta = ktime_us_delta(next_measurement, ktime_get());
508 if (delta > 0)
509 usleep_range(delta, delta + 500);
510 chan->last_measurement = ktime_get();
511
512 mutex_unlock(&chan->lock);
513
514 ret = i2c_smbus_read_word_data(data->client, chan->reg);
515 if (ret < 0)
516 return ret;
517
518 *val = ret;
519
520 return 0;
521 }
522
vcnl4000_measure_light(struct vcnl4000_data * data,int * val)523 static int vcnl4000_measure_light(struct vcnl4000_data *data, int *val)
524 {
525 return vcnl4000_measure(data,
526 VCNL4000_AL_OD, VCNL4000_AL_RDY,
527 VCNL4000_AL_RESULT_HI, val);
528 }
529
vcnl4200_measure_light(struct vcnl4000_data * data,int * val)530 static int vcnl4200_measure_light(struct vcnl4000_data *data, int *val)
531 {
532 return vcnl4200_measure(data, &data->vcnl4200_al, val);
533 }
534
vcnl4000_measure_proximity(struct vcnl4000_data * data,int * val)535 static int vcnl4000_measure_proximity(struct vcnl4000_data *data, int *val)
536 {
537 return vcnl4000_measure(data,
538 VCNL4000_PS_OD, VCNL4000_PS_RDY,
539 VCNL4000_PS_RESULT_HI, val);
540 }
541
vcnl4200_measure_proximity(struct vcnl4000_data * data,int * val)542 static int vcnl4200_measure_proximity(struct vcnl4000_data *data, int *val)
543 {
544 return vcnl4200_measure(data, &data->vcnl4200_ps, val);
545 }
546
vcnl4010_read_proxy_samp_freq(struct vcnl4000_data * data,int * val,int * val2)547 static int vcnl4010_read_proxy_samp_freq(struct vcnl4000_data *data, int *val,
548 int *val2)
549 {
550 int ret;
551
552 ret = i2c_smbus_read_byte_data(data->client, VCNL4010_PROX_RATE);
553 if (ret < 0)
554 return ret;
555
556 if (ret >= ARRAY_SIZE(vcnl4010_prox_sampling_frequency))
557 return -EINVAL;
558
559 *val = vcnl4010_prox_sampling_frequency[ret][0];
560 *val2 = vcnl4010_prox_sampling_frequency[ret][1];
561
562 return 0;
563 }
564
vcnl4010_is_in_periodic_mode(struct vcnl4000_data * data)565 static bool vcnl4010_is_in_periodic_mode(struct vcnl4000_data *data)
566 {
567 int ret;
568
569 ret = i2c_smbus_read_byte_data(data->client, VCNL4000_COMMAND);
570 if (ret < 0)
571 return false;
572
573 return !!(ret & VCNL4000_SELF_TIMED_EN);
574 }
575
vcnl4000_set_pm_runtime_state(struct vcnl4000_data * data,bool on)576 static int vcnl4000_set_pm_runtime_state(struct vcnl4000_data *data, bool on)
577 {
578 struct device *dev = &data->client->dev;
579 int ret;
580
581 if (on) {
582 ret = pm_runtime_resume_and_get(dev);
583 } else {
584 pm_runtime_mark_last_busy(dev);
585 ret = pm_runtime_put_autosuspend(dev);
586 }
587
588 return ret;
589 }
590
vcnl4040_read_als_it(struct vcnl4000_data * data,int * val,int * val2)591 static int vcnl4040_read_als_it(struct vcnl4000_data *data, int *val, int *val2)
592 {
593 int ret;
594
595 ret = i2c_smbus_read_word_data(data->client, VCNL4200_AL_CONF);
596 if (ret < 0)
597 return ret;
598
599 ret = FIELD_GET(VCNL4040_ALS_CONF_IT, ret);
600 if (ret >= data->chip_spec->num_als_it_times)
601 return -EINVAL;
602
603 *val = (*data->chip_spec->als_it_times)[ret][0];
604 *val2 = (*data->chip_spec->als_it_times)[ret][1];
605
606 return 0;
607 }
608
vcnl4040_write_als_it(struct vcnl4000_data * data,int val)609 static ssize_t vcnl4040_write_als_it(struct vcnl4000_data *data, int val)
610 {
611 unsigned int i;
612 int ret;
613 u16 regval;
614
615 for (i = 0; i < data->chip_spec->num_als_it_times; i++) {
616 if (val == (*data->chip_spec->als_it_times)[i][1])
617 break;
618 }
619
620 if (i == data->chip_spec->num_als_it_times)
621 return -EINVAL;
622
623 data->vcnl4200_al.sampling_rate = ktime_set(0, val * 1200);
624 data->al_scale = div_u64(mul_u32_u32(data->chip_spec->ulux_step,
625 (*data->chip_spec->als_it_times)[0][1]),
626 val);
627
628 mutex_lock(&data->vcnl4000_lock);
629
630 ret = i2c_smbus_read_word_data(data->client, VCNL4200_AL_CONF);
631 if (ret < 0)
632 goto out_unlock;
633
634 regval = FIELD_PREP(VCNL4040_ALS_CONF_IT, i);
635 regval |= (ret & ~VCNL4040_ALS_CONF_IT);
636 ret = i2c_smbus_write_word_data(data->client,
637 VCNL4200_AL_CONF,
638 regval);
639
640 out_unlock:
641 mutex_unlock(&data->vcnl4000_lock);
642 return ret;
643 }
644
vcnl4040_read_ps_it(struct vcnl4000_data * data,int * val,int * val2)645 static int vcnl4040_read_ps_it(struct vcnl4000_data *data, int *val, int *val2)
646 {
647 int ret;
648
649 ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1);
650 if (ret < 0)
651 return ret;
652
653 ret = FIELD_GET(VCNL4040_PS_CONF2_PS_IT, ret);
654
655 if (ret >= data->chip_spec->num_ps_it_times)
656 return -EINVAL;
657
658 *val = (*data->chip_spec->ps_it_times)[ret][0];
659 *val2 = (*data->chip_spec->ps_it_times)[ret][1];
660
661 return 0;
662 }
663
vcnl4040_write_ps_it(struct vcnl4000_data * data,int val)664 static ssize_t vcnl4040_write_ps_it(struct vcnl4000_data *data, int val)
665 {
666 unsigned int i;
667 int ret, index = -1;
668 u16 regval;
669
670 for (i = 0; i < data->chip_spec->num_ps_it_times; i++) {
671 if (val == (*data->chip_spec->ps_it_times)[i][1]) {
672 index = i;
673 break;
674 }
675 }
676
677 if (index < 0)
678 return -EINVAL;
679
680 data->vcnl4200_ps.sampling_rate = ktime_set(0, val * 60 * NSEC_PER_USEC);
681
682 mutex_lock(&data->vcnl4000_lock);
683
684 ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1);
685 if (ret < 0)
686 goto out;
687
688 regval = (ret & ~VCNL4040_PS_CONF2_PS_IT) |
689 FIELD_PREP(VCNL4040_PS_CONF2_PS_IT, index);
690 ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF1,
691 regval);
692
693 out:
694 mutex_unlock(&data->vcnl4000_lock);
695 return ret;
696 }
697
vcnl4040_read_als_period(struct vcnl4000_data * data,int * val,int * val2)698 static ssize_t vcnl4040_read_als_period(struct vcnl4000_data *data, int *val, int *val2)
699 {
700 int ret, ret_pers, it;
701 int64_t val_c;
702
703 ret = i2c_smbus_read_word_data(data->client, VCNL4200_AL_CONF);
704 if (ret < 0)
705 return ret;
706
707 ret_pers = FIELD_GET(VCNL4040_ALS_CONF_PERS, ret);
708 if (ret_pers >= ARRAY_SIZE(vcnl4040_als_persistence))
709 return -EINVAL;
710
711 it = FIELD_GET(VCNL4040_ALS_CONF_IT, ret);
712 if (it >= data->chip_spec->num_als_it_times)
713 return -EINVAL;
714
715 val_c = mul_u32_u32((*data->chip_spec->als_it_times)[it][1],
716 vcnl4040_als_persistence[ret_pers]);
717 *val = div_u64_rem(val_c, MICRO, val2);
718
719 return IIO_VAL_INT_PLUS_MICRO;
720 }
721
vcnl4040_write_als_period(struct vcnl4000_data * data,int val,int val2)722 static ssize_t vcnl4040_write_als_period(struct vcnl4000_data *data, int val, int val2)
723 {
724 unsigned int i;
725 int ret, it;
726 u16 regval;
727 u64 val_n = mul_u32_u32(val, MICRO) + val2;
728
729 ret = i2c_smbus_read_word_data(data->client, VCNL4200_AL_CONF);
730 if (ret < 0)
731 return ret;
732
733 it = FIELD_GET(VCNL4040_ALS_CONF_IT, ret);
734 if (it >= data->chip_spec->num_als_it_times)
735 return -EINVAL;
736
737 for (i = 0; i < ARRAY_SIZE(vcnl4040_als_persistence) - 1; i++) {
738 if (val_n < mul_u32_u32(vcnl4040_als_persistence[i],
739 (*data->chip_spec->als_it_times)[it][1]))
740 break;
741 }
742
743 mutex_lock(&data->vcnl4000_lock);
744
745 ret = i2c_smbus_read_word_data(data->client, VCNL4200_AL_CONF);
746 if (ret < 0)
747 goto out_unlock;
748
749 regval = FIELD_PREP(VCNL4040_ALS_CONF_PERS, i);
750 regval |= (ret & ~VCNL4040_ALS_CONF_PERS);
751 ret = i2c_smbus_write_word_data(data->client, VCNL4200_AL_CONF,
752 regval);
753
754 out_unlock:
755 mutex_unlock(&data->vcnl4000_lock);
756 return ret;
757 }
758
vcnl4040_read_ps_period(struct vcnl4000_data * data,int * val,int * val2)759 static ssize_t vcnl4040_read_ps_period(struct vcnl4000_data *data, int *val, int *val2)
760 {
761 int ret, ret_pers, it;
762
763 ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1);
764 if (ret < 0)
765 return ret;
766
767 ret_pers = FIELD_GET(VCNL4040_CONF1_PS_PERS, ret);
768 if (ret_pers >= ARRAY_SIZE(vcnl4040_ps_persistence))
769 return -EINVAL;
770
771 it = FIELD_GET(VCNL4040_PS_CONF2_PS_IT, ret);
772 if (it >= data->chip_spec->num_ps_it_times)
773 return -EINVAL;
774
775 *val = (*data->chip_spec->ps_it_times)[it][0];
776 *val2 = (*data->chip_spec->ps_it_times)[it][1] *
777 vcnl4040_ps_persistence[ret_pers];
778
779 return IIO_VAL_INT_PLUS_MICRO;
780 }
781
vcnl4040_write_ps_period(struct vcnl4000_data * data,int val,int val2)782 static ssize_t vcnl4040_write_ps_period(struct vcnl4000_data *data, int val, int val2)
783 {
784 int ret, it, i;
785 u16 regval;
786
787 ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1);
788 if (ret < 0)
789 return ret;
790
791 it = FIELD_GET(VCNL4040_PS_CONF2_PS_IT, ret);
792 if (it >= data->chip_spec->num_ps_it_times)
793 return -EINVAL;
794
795 if (val > 0)
796 i = ARRAY_SIZE(vcnl4040_ps_persistence) - 1;
797 else {
798 for (i = 0; i < ARRAY_SIZE(vcnl4040_ps_persistence) - 1; i++) {
799 if (val2 <= vcnl4040_ps_persistence[i] *
800 (*data->chip_spec->ps_it_times)[it][1])
801 break;
802 }
803 }
804
805 mutex_lock(&data->vcnl4000_lock);
806
807 ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1);
808 if (ret < 0)
809 goto out_unlock;
810
811 regval = FIELD_PREP(VCNL4040_CONF1_PS_PERS, i);
812 regval |= (ret & ~VCNL4040_CONF1_PS_PERS);
813 ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF1,
814 regval);
815
816 out_unlock:
817 mutex_unlock(&data->vcnl4000_lock);
818 return ret;
819 }
820
vcnl4040_read_ps_oversampling_ratio(struct vcnl4000_data * data,int * val)821 static ssize_t vcnl4040_read_ps_oversampling_ratio(struct vcnl4000_data *data, int *val)
822 {
823 int ret;
824
825 ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF3);
826 if (ret < 0)
827 return ret;
828
829 ret = FIELD_GET(VCNL4040_PS_CONF3_MPS, ret);
830 if (ret >= ARRAY_SIZE(vcnl4040_ps_oversampling_ratio))
831 return -EINVAL;
832
833 *val = vcnl4040_ps_oversampling_ratio[ret];
834
835 return ret;
836 }
837
vcnl4040_write_ps_oversampling_ratio(struct vcnl4000_data * data,int val)838 static ssize_t vcnl4040_write_ps_oversampling_ratio(struct vcnl4000_data *data, int val)
839 {
840 unsigned int i;
841 int ret;
842 u16 regval;
843
844 for (i = 0; i < ARRAY_SIZE(vcnl4040_ps_oversampling_ratio); i++) {
845 if (val == vcnl4040_ps_oversampling_ratio[i])
846 break;
847 }
848
849 if (i >= ARRAY_SIZE(vcnl4040_ps_oversampling_ratio))
850 return -EINVAL;
851
852 mutex_lock(&data->vcnl4000_lock);
853
854 ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF3);
855 if (ret < 0)
856 goto out_unlock;
857
858 regval = FIELD_PREP(VCNL4040_PS_CONF3_MPS, i);
859 regval |= (ret & ~VCNL4040_PS_CONF3_MPS);
860 ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF3,
861 regval);
862
863 out_unlock:
864 mutex_unlock(&data->vcnl4000_lock);
865 return ret;
866 }
867
vcnl4040_read_ps_calibbias(struct vcnl4000_data * data,int * val,int * val2)868 static ssize_t vcnl4040_read_ps_calibbias(struct vcnl4000_data *data, int *val, int *val2)
869 {
870 int ret;
871
872 ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF3);
873 if (ret < 0)
874 return ret;
875
876 ret = FIELD_GET(VCNL4040_PS_MS_LED_I, ret);
877 if (ret >= ARRAY_SIZE(vcnl4040_ps_calibbias_ua))
878 return -EINVAL;
879
880 *val = vcnl4040_ps_calibbias_ua[ret][0];
881 *val2 = vcnl4040_ps_calibbias_ua[ret][1];
882
883 return ret;
884 }
885
vcnl4040_write_ps_calibbias(struct vcnl4000_data * data,int val)886 static ssize_t vcnl4040_write_ps_calibbias(struct vcnl4000_data *data, int val)
887 {
888 unsigned int i;
889 int ret;
890 u16 regval;
891
892 for (i = 0; i < ARRAY_SIZE(vcnl4040_ps_calibbias_ua); i++) {
893 if (val == vcnl4040_ps_calibbias_ua[i][1])
894 break;
895 }
896
897 if (i >= ARRAY_SIZE(vcnl4040_ps_calibbias_ua))
898 return -EINVAL;
899
900 mutex_lock(&data->vcnl4000_lock);
901
902 ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF3);
903 if (ret < 0)
904 goto out_unlock;
905
906 regval = (ret & ~VCNL4040_PS_MS_LED_I);
907 regval |= FIELD_PREP(VCNL4040_PS_MS_LED_I, i);
908 ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF3,
909 regval);
910
911 out_unlock:
912 mutex_unlock(&data->vcnl4000_lock);
913 return ret;
914 }
915
vcnl4000_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long mask)916 static int vcnl4000_read_raw(struct iio_dev *indio_dev,
917 struct iio_chan_spec const *chan,
918 int *val, int *val2, long mask)
919 {
920 int ret;
921 struct vcnl4000_data *data = iio_priv(indio_dev);
922
923 switch (mask) {
924 case IIO_CHAN_INFO_RAW:
925 ret = vcnl4000_set_pm_runtime_state(data, true);
926 if (ret < 0)
927 return ret;
928
929 switch (chan->type) {
930 case IIO_LIGHT:
931 ret = data->chip_spec->measure_light(data, val);
932 if (!ret)
933 ret = IIO_VAL_INT;
934 break;
935 case IIO_PROXIMITY:
936 ret = data->chip_spec->measure_proximity(data, val);
937 *val2 = data->ps_scale;
938 if (!ret)
939 ret = IIO_VAL_FRACTIONAL;
940 break;
941 default:
942 ret = -EINVAL;
943 }
944 vcnl4000_set_pm_runtime_state(data, false);
945 return ret;
946 case IIO_CHAN_INFO_SCALE:
947 if (chan->type != IIO_LIGHT)
948 return -EINVAL;
949
950 *val = 0;
951 *val2 = data->al_scale;
952 return IIO_VAL_INT_PLUS_MICRO;
953 case IIO_CHAN_INFO_INT_TIME:
954 switch (chan->type) {
955 case IIO_LIGHT:
956 ret = vcnl4040_read_als_it(data, val, val2);
957 break;
958 case IIO_PROXIMITY:
959 ret = vcnl4040_read_ps_it(data, val, val2);
960 break;
961 default:
962 return -EINVAL;
963 }
964 if (ret < 0)
965 return ret;
966 return IIO_VAL_INT_PLUS_MICRO;
967 case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
968 switch (chan->type) {
969 case IIO_PROXIMITY:
970 ret = vcnl4040_read_ps_oversampling_ratio(data, val);
971 if (ret < 0)
972 return ret;
973 return IIO_VAL_INT;
974 default:
975 return -EINVAL;
976 }
977 case IIO_CHAN_INFO_CALIBBIAS:
978 switch (chan->type) {
979 case IIO_PROXIMITY:
980 ret = vcnl4040_read_ps_calibbias(data, val, val2);
981 if (ret < 0)
982 return ret;
983 return IIO_VAL_INT_PLUS_MICRO;
984 default:
985 return -EINVAL;
986 }
987 default:
988 return -EINVAL;
989 }
990 }
991
vcnl4040_write_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int val,int val2,long mask)992 static int vcnl4040_write_raw(struct iio_dev *indio_dev,
993 struct iio_chan_spec const *chan,
994 int val, int val2, long mask)
995 {
996 struct vcnl4000_data *data = iio_priv(indio_dev);
997
998 switch (mask) {
999 case IIO_CHAN_INFO_INT_TIME:
1000 if (val != 0)
1001 return -EINVAL;
1002 switch (chan->type) {
1003 case IIO_LIGHT:
1004 return vcnl4040_write_als_it(data, val2);
1005 case IIO_PROXIMITY:
1006 return vcnl4040_write_ps_it(data, val2);
1007 default:
1008 return -EINVAL;
1009 }
1010 case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
1011 switch (chan->type) {
1012 case IIO_PROXIMITY:
1013 return vcnl4040_write_ps_oversampling_ratio(data, val);
1014 default:
1015 return -EINVAL;
1016 }
1017 case IIO_CHAN_INFO_CALIBBIAS:
1018 switch (chan->type) {
1019 case IIO_PROXIMITY:
1020 return vcnl4040_write_ps_calibbias(data, val2);
1021 default:
1022 return -EINVAL;
1023 }
1024 default:
1025 return -EINVAL;
1026 }
1027 }
1028
vcnl4040_read_avail(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,const int ** vals,int * type,int * length,long mask)1029 static int vcnl4040_read_avail(struct iio_dev *indio_dev,
1030 struct iio_chan_spec const *chan,
1031 const int **vals, int *type, int *length,
1032 long mask)
1033 {
1034 struct vcnl4000_data *data = iio_priv(indio_dev);
1035
1036 switch (mask) {
1037 case IIO_CHAN_INFO_INT_TIME:
1038 switch (chan->type) {
1039 case IIO_LIGHT:
1040 *vals = (int *)(*data->chip_spec->als_it_times);
1041 *length = 2 * data->chip_spec->num_als_it_times;
1042 break;
1043 case IIO_PROXIMITY:
1044 *vals = (int *)(*data->chip_spec->ps_it_times);
1045 *length = 2 * data->chip_spec->num_ps_it_times;
1046 break;
1047 default:
1048 return -EINVAL;
1049 }
1050 *type = IIO_VAL_INT_PLUS_MICRO;
1051 return IIO_AVAIL_LIST;
1052 case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
1053 switch (chan->type) {
1054 case IIO_PROXIMITY:
1055 *vals = (int *)vcnl4040_ps_oversampling_ratio;
1056 *length = ARRAY_SIZE(vcnl4040_ps_oversampling_ratio);
1057 *type = IIO_VAL_INT;
1058 return IIO_AVAIL_LIST;
1059 default:
1060 return -EINVAL;
1061 }
1062 case IIO_CHAN_INFO_CALIBBIAS:
1063 switch (chan->type) {
1064 case IIO_PROXIMITY:
1065 *vals = (int *)vcnl4040_ps_calibbias_ua;
1066 *length = 2 * ARRAY_SIZE(vcnl4040_ps_calibbias_ua);
1067 *type = IIO_VAL_INT_PLUS_MICRO;
1068 return IIO_AVAIL_LIST;
1069 default:
1070 return -EINVAL;
1071 }
1072 default:
1073 return -EINVAL;
1074 }
1075 }
1076
vcnl4010_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long mask)1077 static int vcnl4010_read_raw(struct iio_dev *indio_dev,
1078 struct iio_chan_spec const *chan,
1079 int *val, int *val2, long mask)
1080 {
1081 int ret;
1082 struct vcnl4000_data *data = iio_priv(indio_dev);
1083
1084 switch (mask) {
1085 case IIO_CHAN_INFO_RAW:
1086 case IIO_CHAN_INFO_SCALE:
1087 if (!iio_device_claim_direct(indio_dev))
1088 return -EBUSY;
1089
1090 /* Protect against event capture. */
1091 if (vcnl4010_is_in_periodic_mode(data)) {
1092 ret = -EBUSY;
1093 } else {
1094 ret = vcnl4000_read_raw(indio_dev, chan, val, val2,
1095 mask);
1096 }
1097
1098 iio_device_release_direct(indio_dev);
1099 return ret;
1100 case IIO_CHAN_INFO_SAMP_FREQ:
1101 switch (chan->type) {
1102 case IIO_PROXIMITY:
1103 ret = vcnl4010_read_proxy_samp_freq(data, val, val2);
1104 if (ret < 0)
1105 return ret;
1106 return IIO_VAL_INT_PLUS_MICRO;
1107 default:
1108 return -EINVAL;
1109 }
1110 default:
1111 return -EINVAL;
1112 }
1113 }
1114
vcnl4010_read_avail(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,const int ** vals,int * type,int * length,long mask)1115 static int vcnl4010_read_avail(struct iio_dev *indio_dev,
1116 struct iio_chan_spec const *chan,
1117 const int **vals, int *type, int *length,
1118 long mask)
1119 {
1120 switch (mask) {
1121 case IIO_CHAN_INFO_SAMP_FREQ:
1122 *vals = (int *)vcnl4010_prox_sampling_frequency;
1123 *type = IIO_VAL_INT_PLUS_MICRO;
1124 *length = 2 * ARRAY_SIZE(vcnl4010_prox_sampling_frequency);
1125 return IIO_AVAIL_LIST;
1126 default:
1127 return -EINVAL;
1128 }
1129 }
1130
vcnl4010_write_proxy_samp_freq(struct vcnl4000_data * data,int val,int val2)1131 static int vcnl4010_write_proxy_samp_freq(struct vcnl4000_data *data, int val,
1132 int val2)
1133 {
1134 unsigned int i;
1135 int index = -1;
1136
1137 for (i = 0; i < ARRAY_SIZE(vcnl4010_prox_sampling_frequency); i++) {
1138 if (val == vcnl4010_prox_sampling_frequency[i][0] &&
1139 val2 == vcnl4010_prox_sampling_frequency[i][1]) {
1140 index = i;
1141 break;
1142 }
1143 }
1144
1145 if (index < 0)
1146 return -EINVAL;
1147
1148 return i2c_smbus_write_byte_data(data->client, VCNL4010_PROX_RATE,
1149 index);
1150 }
1151
vcnl4010_write_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int val,int val2,long mask)1152 static int vcnl4010_write_raw(struct iio_dev *indio_dev,
1153 struct iio_chan_spec const *chan,
1154 int val, int val2, long mask)
1155 {
1156 int ret;
1157 struct vcnl4000_data *data = iio_priv(indio_dev);
1158
1159 if (!iio_device_claim_direct(indio_dev))
1160 return -EBUSY;
1161
1162 /* Protect against event capture. */
1163 if (vcnl4010_is_in_periodic_mode(data)) {
1164 ret = -EBUSY;
1165 goto end;
1166 }
1167
1168 switch (mask) {
1169 case IIO_CHAN_INFO_SAMP_FREQ:
1170 switch (chan->type) {
1171 case IIO_PROXIMITY:
1172 ret = vcnl4010_write_proxy_samp_freq(data, val, val2);
1173 goto end;
1174 default:
1175 ret = -EINVAL;
1176 goto end;
1177 }
1178 default:
1179 ret = -EINVAL;
1180 goto end;
1181 }
1182
1183 end:
1184 iio_device_release_direct(indio_dev);
1185 return ret;
1186 }
1187
vcnl4010_read_event(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,enum iio_event_type type,enum iio_event_direction dir,enum iio_event_info info,int * val,int * val2)1188 static int vcnl4010_read_event(struct iio_dev *indio_dev,
1189 const struct iio_chan_spec *chan,
1190 enum iio_event_type type,
1191 enum iio_event_direction dir,
1192 enum iio_event_info info,
1193 int *val, int *val2)
1194 {
1195 int ret;
1196 struct vcnl4000_data *data = iio_priv(indio_dev);
1197
1198 switch (info) {
1199 case IIO_EV_INFO_VALUE:
1200 switch (dir) {
1201 case IIO_EV_DIR_RISING:
1202 ret = vcnl4000_read_data(data, VCNL4010_HIGH_THR_HI,
1203 val);
1204 if (ret < 0)
1205 return ret;
1206 return IIO_VAL_INT;
1207 case IIO_EV_DIR_FALLING:
1208 ret = vcnl4000_read_data(data, VCNL4010_LOW_THR_HI,
1209 val);
1210 if (ret < 0)
1211 return ret;
1212 return IIO_VAL_INT;
1213 default:
1214 return -EINVAL;
1215 }
1216 default:
1217 return -EINVAL;
1218 }
1219 }
1220
vcnl4010_write_event(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,enum iio_event_type type,enum iio_event_direction dir,enum iio_event_info info,int val,int val2)1221 static int vcnl4010_write_event(struct iio_dev *indio_dev,
1222 const struct iio_chan_spec *chan,
1223 enum iio_event_type type,
1224 enum iio_event_direction dir,
1225 enum iio_event_info info,
1226 int val, int val2)
1227 {
1228 int ret;
1229 struct vcnl4000_data *data = iio_priv(indio_dev);
1230
1231 switch (info) {
1232 case IIO_EV_INFO_VALUE:
1233 switch (dir) {
1234 case IIO_EV_DIR_RISING:
1235 ret = vcnl4000_write_data(data, VCNL4010_HIGH_THR_HI,
1236 val);
1237 if (ret < 0)
1238 return ret;
1239 return IIO_VAL_INT;
1240 case IIO_EV_DIR_FALLING:
1241 ret = vcnl4000_write_data(data, VCNL4010_LOW_THR_HI,
1242 val);
1243 if (ret < 0)
1244 return ret;
1245 return IIO_VAL_INT;
1246 default:
1247 return -EINVAL;
1248 }
1249 default:
1250 return -EINVAL;
1251 }
1252 }
1253
vcnl4040_read_event(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,enum iio_event_type type,enum iio_event_direction dir,enum iio_event_info info,int * val,int * val2)1254 static int vcnl4040_read_event(struct iio_dev *indio_dev,
1255 const struct iio_chan_spec *chan,
1256 enum iio_event_type type,
1257 enum iio_event_direction dir,
1258 enum iio_event_info info,
1259 int *val, int *val2)
1260 {
1261 int ret;
1262 struct vcnl4000_data *data = iio_priv(indio_dev);
1263
1264 switch (chan->type) {
1265 case IIO_LIGHT:
1266 switch (info) {
1267 case IIO_EV_INFO_PERIOD:
1268 return vcnl4040_read_als_period(data, val, val2);
1269 case IIO_EV_INFO_VALUE:
1270 switch (dir) {
1271 case IIO_EV_DIR_RISING:
1272 ret = i2c_smbus_read_word_data(data->client,
1273 VCNL4040_ALS_THDH_LM);
1274 break;
1275 case IIO_EV_DIR_FALLING:
1276 ret = i2c_smbus_read_word_data(data->client,
1277 VCNL4040_ALS_THDL_LM);
1278 break;
1279 default:
1280 return -EINVAL;
1281 }
1282 break;
1283 default:
1284 return -EINVAL;
1285 }
1286 break;
1287 case IIO_PROXIMITY:
1288 switch (info) {
1289 case IIO_EV_INFO_PERIOD:
1290 return vcnl4040_read_ps_period(data, val, val2);
1291 case IIO_EV_INFO_VALUE:
1292 switch (dir) {
1293 case IIO_EV_DIR_RISING:
1294 ret = i2c_smbus_read_word_data(data->client,
1295 VCNL4040_PS_THDH_LM);
1296 break;
1297 case IIO_EV_DIR_FALLING:
1298 ret = i2c_smbus_read_word_data(data->client,
1299 VCNL4040_PS_THDL_LM);
1300 break;
1301 default:
1302 return -EINVAL;
1303 }
1304 break;
1305 default:
1306 return -EINVAL;
1307 }
1308 break;
1309 default:
1310 return -EINVAL;
1311 }
1312 if (ret < 0)
1313 return ret;
1314 *val = ret;
1315 return IIO_VAL_INT;
1316 }
1317
vcnl4040_write_event(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,enum iio_event_type type,enum iio_event_direction dir,enum iio_event_info info,int val,int val2)1318 static int vcnl4040_write_event(struct iio_dev *indio_dev,
1319 const struct iio_chan_spec *chan,
1320 enum iio_event_type type,
1321 enum iio_event_direction dir,
1322 enum iio_event_info info,
1323 int val, int val2)
1324 {
1325 int ret;
1326 struct vcnl4000_data *data = iio_priv(indio_dev);
1327
1328 switch (chan->type) {
1329 case IIO_LIGHT:
1330 switch (info) {
1331 case IIO_EV_INFO_PERIOD:
1332 return vcnl4040_write_als_period(data, val, val2);
1333 case IIO_EV_INFO_VALUE:
1334 switch (dir) {
1335 case IIO_EV_DIR_RISING:
1336 ret = i2c_smbus_write_word_data(data->client,
1337 VCNL4040_ALS_THDH_LM,
1338 val);
1339 break;
1340 case IIO_EV_DIR_FALLING:
1341 ret = i2c_smbus_write_word_data(data->client,
1342 VCNL4040_ALS_THDL_LM,
1343 val);
1344 break;
1345 default:
1346 return -EINVAL;
1347 }
1348 break;
1349 default:
1350 return -EINVAL;
1351 }
1352 break;
1353 case IIO_PROXIMITY:
1354 switch (info) {
1355 case IIO_EV_INFO_PERIOD:
1356 return vcnl4040_write_ps_period(data, val, val2);
1357 case IIO_EV_INFO_VALUE:
1358 switch (dir) {
1359 case IIO_EV_DIR_RISING:
1360 ret = i2c_smbus_write_word_data(data->client,
1361 VCNL4040_PS_THDH_LM,
1362 val);
1363 break;
1364 case IIO_EV_DIR_FALLING:
1365 ret = i2c_smbus_write_word_data(data->client,
1366 VCNL4040_PS_THDL_LM,
1367 val);
1368 break;
1369 default:
1370 return -EINVAL;
1371 }
1372 break;
1373 default:
1374 return -EINVAL;
1375 }
1376 break;
1377 default:
1378 return -EINVAL;
1379 }
1380 if (ret < 0)
1381 return ret;
1382 return IIO_VAL_INT;
1383 }
1384
vcnl4010_is_thr_enabled(struct vcnl4000_data * data)1385 static bool vcnl4010_is_thr_enabled(struct vcnl4000_data *data)
1386 {
1387 int ret;
1388
1389 ret = i2c_smbus_read_byte_data(data->client, VCNL4010_INT_CTRL);
1390 if (ret < 0)
1391 return false;
1392
1393 return !!(ret & VCNL4010_INT_THR_EN);
1394 }
1395
vcnl4010_read_event_config(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,enum iio_event_type type,enum iio_event_direction dir)1396 static int vcnl4010_read_event_config(struct iio_dev *indio_dev,
1397 const struct iio_chan_spec *chan,
1398 enum iio_event_type type,
1399 enum iio_event_direction dir)
1400 {
1401 struct vcnl4000_data *data = iio_priv(indio_dev);
1402
1403 switch (chan->type) {
1404 case IIO_PROXIMITY:
1405 return vcnl4010_is_thr_enabled(data);
1406 default:
1407 return -EINVAL;
1408 }
1409 }
1410
vcnl4010_config_threshold_enable(struct vcnl4000_data * data)1411 static int vcnl4010_config_threshold_enable(struct vcnl4000_data *data)
1412 {
1413 int ret;
1414
1415 /* Enable periodic measurement of proximity data. */
1416 ret = i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND,
1417 VCNL4000_SELF_TIMED_EN | VCNL4000_PROX_EN);
1418 if (ret < 0)
1419 return ret;
1420
1421 /*
1422 * Enable interrupts on threshold, for proximity data by
1423 * default.
1424 */
1425 return i2c_smbus_write_byte_data(data->client, VCNL4010_INT_CTRL,
1426 VCNL4010_INT_THR_EN);
1427 }
1428
vcnl4010_config_threshold_disable(struct vcnl4000_data * data)1429 static int vcnl4010_config_threshold_disable(struct vcnl4000_data *data)
1430 {
1431 int ret;
1432
1433 if (!vcnl4010_is_thr_enabled(data))
1434 return 0;
1435
1436 ret = i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, 0);
1437 if (ret < 0)
1438 return ret;
1439
1440 return i2c_smbus_write_byte_data(data->client, VCNL4010_INT_CTRL, 0);
1441 }
1442
vcnl4010_config_threshold(struct iio_dev * indio_dev,bool state)1443 static int vcnl4010_config_threshold(struct iio_dev *indio_dev, bool state)
1444 {
1445 struct vcnl4000_data *data = iio_priv(indio_dev);
1446 int ret;
1447
1448 if (state) {
1449 if (!iio_device_claim_direct(indio_dev))
1450 return -EBUSY;
1451 ret = vcnl4010_config_threshold_enable(data);
1452 iio_device_release_direct(indio_dev);
1453 return ret;
1454 } else {
1455 return vcnl4010_config_threshold_disable(data);
1456 }
1457 }
1458
vcnl4010_write_event_config(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,enum iio_event_type type,enum iio_event_direction dir,bool state)1459 static int vcnl4010_write_event_config(struct iio_dev *indio_dev,
1460 const struct iio_chan_spec *chan,
1461 enum iio_event_type type,
1462 enum iio_event_direction dir,
1463 bool state)
1464 {
1465 switch (chan->type) {
1466 case IIO_PROXIMITY:
1467 return vcnl4010_config_threshold(indio_dev, state);
1468 default:
1469 return -EINVAL;
1470 }
1471 }
1472
vcnl4040_read_event_config(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,enum iio_event_type type,enum iio_event_direction dir)1473 static int vcnl4040_read_event_config(struct iio_dev *indio_dev,
1474 const struct iio_chan_spec *chan,
1475 enum iio_event_type type,
1476 enum iio_event_direction dir)
1477 {
1478 int ret;
1479 struct vcnl4000_data *data = iio_priv(indio_dev);
1480
1481 switch (chan->type) {
1482 case IIO_LIGHT:
1483 ret = i2c_smbus_read_word_data(data->client, VCNL4200_AL_CONF);
1484 if (ret < 0)
1485 return ret;
1486
1487 data->als_int = FIELD_GET(VCNL4040_ALS_CONF_INT_EN, ret);
1488
1489 return data->als_int;
1490 case IIO_PROXIMITY:
1491 ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1);
1492 if (ret < 0)
1493 return ret;
1494
1495 data->ps_int = FIELD_GET(VCNL4040_PS_CONF2_PS_INT, ret);
1496
1497 return (dir == IIO_EV_DIR_RISING) ?
1498 FIELD_GET(VCNL4040_PS_IF_AWAY, ret) :
1499 FIELD_GET(VCNL4040_PS_IF_CLOSE, ret);
1500 default:
1501 return -EINVAL;
1502 }
1503 }
1504
vcnl4040_write_event_config(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,enum iio_event_type type,enum iio_event_direction dir,bool state)1505 static int vcnl4040_write_event_config(struct iio_dev *indio_dev,
1506 const struct iio_chan_spec *chan,
1507 enum iio_event_type type,
1508 enum iio_event_direction dir,
1509 bool state)
1510 {
1511 int ret = -EINVAL;
1512 u16 val, mask;
1513 struct vcnl4000_data *data = iio_priv(indio_dev);
1514
1515 mutex_lock(&data->vcnl4000_lock);
1516
1517 switch (chan->type) {
1518 case IIO_LIGHT:
1519 ret = i2c_smbus_read_word_data(data->client, VCNL4200_AL_CONF);
1520 if (ret < 0)
1521 goto out;
1522
1523 mask = VCNL4040_ALS_CONF_INT_EN;
1524 if (state)
1525 val = (ret | mask);
1526 else
1527 val = (ret & ~mask);
1528
1529 data->als_int = FIELD_GET(VCNL4040_ALS_CONF_INT_EN, val);
1530 ret = i2c_smbus_write_word_data(data->client, VCNL4200_AL_CONF,
1531 val);
1532 break;
1533 case IIO_PROXIMITY:
1534 ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1);
1535 if (ret < 0)
1536 goto out;
1537
1538 if (dir == IIO_EV_DIR_RISING)
1539 mask = VCNL4040_PS_IF_AWAY;
1540 else
1541 mask = VCNL4040_PS_IF_CLOSE;
1542
1543 val = state ? (ret | mask) : (ret & ~mask);
1544
1545 data->ps_int = FIELD_GET(VCNL4040_PS_CONF2_PS_INT, val);
1546 ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF1,
1547 val);
1548 break;
1549 default:
1550 break;
1551 }
1552
1553 out:
1554 mutex_unlock(&data->vcnl4000_lock);
1555
1556 return ret;
1557 }
1558
vcnl4040_irq_thread(int irq,void * p)1559 static irqreturn_t vcnl4040_irq_thread(int irq, void *p)
1560 {
1561 struct iio_dev *indio_dev = p;
1562 struct vcnl4000_data *data = iio_priv(indio_dev);
1563 int ret;
1564
1565 ret = i2c_smbus_read_word_data(data->client, data->chip_spec->int_reg);
1566 if (ret < 0)
1567 return IRQ_HANDLED;
1568
1569 if (ret & VCNL4040_PS_IF_CLOSE) {
1570 iio_push_event(indio_dev,
1571 IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, 0,
1572 IIO_EV_TYPE_THRESH,
1573 IIO_EV_DIR_RISING),
1574 iio_get_time_ns(indio_dev));
1575 }
1576
1577 if (ret & VCNL4040_PS_IF_AWAY) {
1578 iio_push_event(indio_dev,
1579 IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, 0,
1580 IIO_EV_TYPE_THRESH,
1581 IIO_EV_DIR_FALLING),
1582 iio_get_time_ns(indio_dev));
1583 }
1584
1585 if (ret & VCNL4040_ALS_FALLING) {
1586 iio_push_event(indio_dev,
1587 IIO_UNMOD_EVENT_CODE(IIO_LIGHT, 0,
1588 IIO_EV_TYPE_THRESH,
1589 IIO_EV_DIR_FALLING),
1590 iio_get_time_ns(indio_dev));
1591 }
1592
1593 if (ret & VCNL4040_ALS_RISING) {
1594 iio_push_event(indio_dev,
1595 IIO_UNMOD_EVENT_CODE(IIO_LIGHT, 0,
1596 IIO_EV_TYPE_THRESH,
1597 IIO_EV_DIR_RISING),
1598 iio_get_time_ns(indio_dev));
1599 }
1600
1601 return IRQ_HANDLED;
1602 }
1603
vcnl4000_read_near_level(struct iio_dev * indio_dev,uintptr_t priv,const struct iio_chan_spec * chan,char * buf)1604 static ssize_t vcnl4000_read_near_level(struct iio_dev *indio_dev,
1605 uintptr_t priv,
1606 const struct iio_chan_spec *chan,
1607 char *buf)
1608 {
1609 struct vcnl4000_data *data = iio_priv(indio_dev);
1610
1611 return sprintf(buf, "%u\n", data->near_level);
1612 }
1613
vcnl4010_irq_thread(int irq,void * p)1614 static irqreturn_t vcnl4010_irq_thread(int irq, void *p)
1615 {
1616 struct iio_dev *indio_dev = p;
1617 struct vcnl4000_data *data = iio_priv(indio_dev);
1618 unsigned long isr;
1619 int ret;
1620
1621 ret = i2c_smbus_read_byte_data(data->client, VCNL4010_ISR);
1622 if (ret < 0)
1623 goto end;
1624
1625 isr = ret;
1626
1627 if (isr & VCNL4010_INT_THR) {
1628 if (test_bit(VCNL4010_INT_THR_LOW, &isr)) {
1629 iio_push_event(indio_dev,
1630 IIO_UNMOD_EVENT_CODE(
1631 IIO_PROXIMITY,
1632 1,
1633 IIO_EV_TYPE_THRESH,
1634 IIO_EV_DIR_FALLING),
1635 iio_get_time_ns(indio_dev));
1636 }
1637
1638 if (test_bit(VCNL4010_INT_THR_HIGH, &isr)) {
1639 iio_push_event(indio_dev,
1640 IIO_UNMOD_EVENT_CODE(
1641 IIO_PROXIMITY,
1642 1,
1643 IIO_EV_TYPE_THRESH,
1644 IIO_EV_DIR_RISING),
1645 iio_get_time_ns(indio_dev));
1646 }
1647
1648 i2c_smbus_write_byte_data(data->client, VCNL4010_ISR,
1649 isr & VCNL4010_INT_THR);
1650 }
1651
1652 if (isr & VCNL4010_INT_DRDY && iio_buffer_enabled(indio_dev))
1653 iio_trigger_poll_nested(indio_dev->trig);
1654
1655 end:
1656 return IRQ_HANDLED;
1657 }
1658
vcnl4010_trigger_handler(int irq,void * p)1659 static irqreturn_t vcnl4010_trigger_handler(int irq, void *p)
1660 {
1661 struct iio_poll_func *pf = p;
1662 struct iio_dev *indio_dev = pf->indio_dev;
1663 struct vcnl4000_data *data = iio_priv(indio_dev);
1664 const unsigned long *active_scan_mask = indio_dev->active_scan_mask;
1665 u16 buffer[8] __aligned(8) = {0}; /* 1x16-bit + naturally aligned ts */
1666 bool data_read = false;
1667 unsigned long isr;
1668 int val = 0;
1669 int ret;
1670
1671 ret = i2c_smbus_read_byte_data(data->client, VCNL4010_ISR);
1672 if (ret < 0)
1673 goto end;
1674
1675 isr = ret;
1676
1677 if (test_bit(0, active_scan_mask)) {
1678 if (test_bit(VCNL4010_INT_PROXIMITY, &isr)) {
1679 ret = vcnl4000_read_data(data,
1680 VCNL4000_PS_RESULT_HI,
1681 &val);
1682 if (ret < 0)
1683 goto end;
1684
1685 buffer[0] = val;
1686 data_read = true;
1687 }
1688 }
1689
1690 ret = i2c_smbus_write_byte_data(data->client, VCNL4010_ISR,
1691 isr & VCNL4010_INT_DRDY);
1692 if (ret < 0)
1693 goto end;
1694
1695 if (!data_read)
1696 goto end;
1697
1698 iio_push_to_buffers_with_timestamp(indio_dev, buffer,
1699 iio_get_time_ns(indio_dev));
1700
1701 end:
1702 iio_trigger_notify_done(indio_dev->trig);
1703 return IRQ_HANDLED;
1704 }
1705
vcnl4010_buffer_postenable(struct iio_dev * indio_dev)1706 static int vcnl4010_buffer_postenable(struct iio_dev *indio_dev)
1707 {
1708 struct vcnl4000_data *data = iio_priv(indio_dev);
1709 int ret;
1710 int cmd;
1711
1712 /* Do not enable the buffer if we are already capturing events. */
1713 if (vcnl4010_is_in_periodic_mode(data))
1714 return -EBUSY;
1715
1716 ret = i2c_smbus_write_byte_data(data->client, VCNL4010_INT_CTRL,
1717 VCNL4010_INT_PROX_EN);
1718 if (ret < 0)
1719 return ret;
1720
1721 cmd = VCNL4000_SELF_TIMED_EN | VCNL4000_PROX_EN;
1722 return i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, cmd);
1723 }
1724
vcnl4010_buffer_predisable(struct iio_dev * indio_dev)1725 static int vcnl4010_buffer_predisable(struct iio_dev *indio_dev)
1726 {
1727 struct vcnl4000_data *data = iio_priv(indio_dev);
1728 int ret;
1729
1730 ret = i2c_smbus_write_byte_data(data->client, VCNL4010_INT_CTRL, 0);
1731 if (ret < 0)
1732 return ret;
1733
1734 return i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, 0);
1735 }
1736
1737 static const struct iio_buffer_setup_ops vcnl4010_buffer_ops = {
1738 .postenable = &vcnl4010_buffer_postenable,
1739 .predisable = &vcnl4010_buffer_predisable,
1740 };
1741
1742 static const struct iio_chan_spec_ext_info vcnl4000_ext_info[] = {
1743 {
1744 .name = "nearlevel",
1745 .shared = IIO_SEPARATE,
1746 .read = vcnl4000_read_near_level,
1747 },
1748 { }
1749 };
1750
1751 static const struct iio_event_spec vcnl4000_event_spec[] = {
1752 {
1753 .type = IIO_EV_TYPE_THRESH,
1754 .dir = IIO_EV_DIR_RISING,
1755 .mask_separate = BIT(IIO_EV_INFO_VALUE),
1756 }, {
1757 .type = IIO_EV_TYPE_THRESH,
1758 .dir = IIO_EV_DIR_FALLING,
1759 .mask_separate = BIT(IIO_EV_INFO_VALUE),
1760 }, {
1761 .type = IIO_EV_TYPE_THRESH,
1762 .dir = IIO_EV_DIR_EITHER,
1763 .mask_separate = BIT(IIO_EV_INFO_ENABLE),
1764 }
1765 };
1766
1767 static const struct iio_event_spec vcnl4040_als_event_spec[] = {
1768 {
1769 .type = IIO_EV_TYPE_THRESH,
1770 .dir = IIO_EV_DIR_RISING,
1771 .mask_separate = BIT(IIO_EV_INFO_VALUE),
1772 }, {
1773 .type = IIO_EV_TYPE_THRESH,
1774 .dir = IIO_EV_DIR_FALLING,
1775 .mask_separate = BIT(IIO_EV_INFO_VALUE),
1776 }, {
1777 .type = IIO_EV_TYPE_THRESH,
1778 .dir = IIO_EV_DIR_EITHER,
1779 .mask_separate = BIT(IIO_EV_INFO_ENABLE) | BIT(IIO_EV_INFO_PERIOD),
1780 },
1781 };
1782
1783 static const struct iio_event_spec vcnl4040_event_spec[] = {
1784 {
1785 .type = IIO_EV_TYPE_THRESH,
1786 .dir = IIO_EV_DIR_RISING,
1787 .mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE),
1788 }, {
1789 .type = IIO_EV_TYPE_THRESH,
1790 .dir = IIO_EV_DIR_FALLING,
1791 .mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE),
1792 }, {
1793 .type = IIO_EV_TYPE_THRESH,
1794 .dir = IIO_EV_DIR_EITHER,
1795 .mask_separate = BIT(IIO_EV_INFO_PERIOD),
1796 },
1797 };
1798
1799 static const struct iio_chan_spec vcnl4000_channels[] = {
1800 {
1801 .type = IIO_LIGHT,
1802 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
1803 BIT(IIO_CHAN_INFO_SCALE),
1804 }, {
1805 .type = IIO_PROXIMITY,
1806 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
1807 .ext_info = vcnl4000_ext_info,
1808 }
1809 };
1810
1811 static const struct iio_chan_spec vcnl4010_channels[] = {
1812 {
1813 .type = IIO_LIGHT,
1814 .scan_index = -1,
1815 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
1816 BIT(IIO_CHAN_INFO_SCALE),
1817 }, {
1818 .type = IIO_PROXIMITY,
1819 .scan_index = 0,
1820 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
1821 BIT(IIO_CHAN_INFO_SAMP_FREQ),
1822 .info_mask_separate_available = BIT(IIO_CHAN_INFO_SAMP_FREQ),
1823 .event_spec = vcnl4000_event_spec,
1824 .num_event_specs = ARRAY_SIZE(vcnl4000_event_spec),
1825 .ext_info = vcnl4000_ext_info,
1826 .scan_type = {
1827 .sign = 'u',
1828 .realbits = 16,
1829 .storagebits = 16,
1830 .endianness = IIO_CPU,
1831 },
1832 },
1833 IIO_CHAN_SOFT_TIMESTAMP(1),
1834 };
1835
1836 static const struct iio_chan_spec vcnl4040_channels[] = {
1837 {
1838 .type = IIO_LIGHT,
1839 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
1840 BIT(IIO_CHAN_INFO_SCALE) |
1841 BIT(IIO_CHAN_INFO_INT_TIME),
1842 .info_mask_separate_available = BIT(IIO_CHAN_INFO_INT_TIME),
1843 .event_spec = vcnl4040_als_event_spec,
1844 .num_event_specs = ARRAY_SIZE(vcnl4040_als_event_spec),
1845 }, {
1846 .type = IIO_PROXIMITY,
1847 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
1848 BIT(IIO_CHAN_INFO_INT_TIME) |
1849 BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO) |
1850 BIT(IIO_CHAN_INFO_CALIBBIAS),
1851 .info_mask_separate_available = BIT(IIO_CHAN_INFO_INT_TIME) |
1852 BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO) |
1853 BIT(IIO_CHAN_INFO_CALIBBIAS),
1854 .ext_info = vcnl4000_ext_info,
1855 .event_spec = vcnl4040_event_spec,
1856 .num_event_specs = ARRAY_SIZE(vcnl4040_event_spec),
1857 }
1858 };
1859
1860 static const struct iio_info vcnl4000_info = {
1861 .read_raw = vcnl4000_read_raw,
1862 };
1863
1864 static const struct iio_info vcnl4010_info = {
1865 .read_raw = vcnl4010_read_raw,
1866 .read_avail = vcnl4010_read_avail,
1867 .write_raw = vcnl4010_write_raw,
1868 .read_event_value = vcnl4010_read_event,
1869 .write_event_value = vcnl4010_write_event,
1870 .read_event_config = vcnl4010_read_event_config,
1871 .write_event_config = vcnl4010_write_event_config,
1872 };
1873
1874 static const struct iio_info vcnl4040_info = {
1875 .read_raw = vcnl4000_read_raw,
1876 .write_raw = vcnl4040_write_raw,
1877 .read_event_value = vcnl4040_read_event,
1878 .write_event_value = vcnl4040_write_event,
1879 .read_event_config = vcnl4040_read_event_config,
1880 .write_event_config = vcnl4040_write_event_config,
1881 .read_avail = vcnl4040_read_avail,
1882 };
1883
1884 static const struct vcnl4000_chip_spec vcnl4000_chip_spec_cfg[] = {
1885 [VCNL4000] = {
1886 .prod = "VCNL4000",
1887 .init = vcnl4000_init,
1888 .measure_light = vcnl4000_measure_light,
1889 .measure_proximity = vcnl4000_measure_proximity,
1890 .set_power_state = vcnl4000_set_power_state,
1891 .channels = vcnl4000_channels,
1892 .num_channels = ARRAY_SIZE(vcnl4000_channels),
1893 .info = &vcnl4000_info,
1894 },
1895 [VCNL4010] = {
1896 .prod = "VCNL4010/4020",
1897 .init = vcnl4000_init,
1898 .measure_light = vcnl4000_measure_light,
1899 .measure_proximity = vcnl4000_measure_proximity,
1900 .set_power_state = vcnl4000_set_power_state,
1901 .channels = vcnl4010_channels,
1902 .num_channels = ARRAY_SIZE(vcnl4010_channels),
1903 .info = &vcnl4010_info,
1904 .irq_thread = vcnl4010_irq_thread,
1905 .trig_buffer_func = vcnl4010_trigger_handler,
1906 .buffer_setup_ops = &vcnl4010_buffer_ops,
1907 },
1908 [VCNL4040] = {
1909 .prod = "VCNL4040",
1910 .init = vcnl4200_init,
1911 .measure_light = vcnl4200_measure_light,
1912 .measure_proximity = vcnl4200_measure_proximity,
1913 .set_power_state = vcnl4200_set_power_state,
1914 .channels = vcnl4040_channels,
1915 .num_channels = ARRAY_SIZE(vcnl4040_channels),
1916 .info = &vcnl4040_info,
1917 .irq_thread = vcnl4040_irq_thread,
1918 .int_reg = VCNL4040_INT_FLAGS,
1919 .ps_it_times = &vcnl4040_ps_it_times,
1920 .num_ps_it_times = ARRAY_SIZE(vcnl4040_ps_it_times),
1921 .als_it_times = &vcnl4040_als_it_times,
1922 .num_als_it_times = ARRAY_SIZE(vcnl4040_als_it_times),
1923 .ulux_step = 100000,
1924 },
1925 [VCNL4200] = {
1926 .prod = "VCNL4200",
1927 .init = vcnl4200_init,
1928 .measure_light = vcnl4200_measure_light,
1929 .measure_proximity = vcnl4200_measure_proximity,
1930 .set_power_state = vcnl4200_set_power_state,
1931 .channels = vcnl4040_channels,
1932 .num_channels = ARRAY_SIZE(vcnl4000_channels),
1933 .info = &vcnl4040_info,
1934 .irq_thread = vcnl4040_irq_thread,
1935 .int_reg = VCNL4200_INT_FLAGS,
1936 .ps_it_times = &vcnl4200_ps_it_times,
1937 .num_ps_it_times = ARRAY_SIZE(vcnl4200_ps_it_times),
1938 .als_it_times = &vcnl4200_als_it_times,
1939 .num_als_it_times = ARRAY_SIZE(vcnl4200_als_it_times),
1940 .ulux_step = 24000,
1941 },
1942 };
1943
1944 static const struct iio_trigger_ops vcnl4010_trigger_ops = {
1945 .validate_device = iio_trigger_validate_own_device,
1946 };
1947
vcnl4010_probe_trigger(struct iio_dev * indio_dev)1948 static int vcnl4010_probe_trigger(struct iio_dev *indio_dev)
1949 {
1950 struct vcnl4000_data *data = iio_priv(indio_dev);
1951 struct i2c_client *client = data->client;
1952 struct iio_trigger *trigger;
1953
1954 trigger = devm_iio_trigger_alloc(&client->dev, "%s-dev%d",
1955 indio_dev->name,
1956 iio_device_id(indio_dev));
1957 if (!trigger)
1958 return -ENOMEM;
1959
1960 trigger->ops = &vcnl4010_trigger_ops;
1961 iio_trigger_set_drvdata(trigger, indio_dev);
1962
1963 return devm_iio_trigger_register(&client->dev, trigger);
1964 }
1965
vcnl4000_probe(struct i2c_client * client)1966 static int vcnl4000_probe(struct i2c_client *client)
1967 {
1968 const struct i2c_device_id *id = i2c_client_get_device_id(client);
1969 struct vcnl4000_data *data;
1970 struct iio_dev *indio_dev;
1971 int ret;
1972
1973 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
1974 if (!indio_dev)
1975 return -ENOMEM;
1976
1977 data = iio_priv(indio_dev);
1978 i2c_set_clientdata(client, indio_dev);
1979 data->client = client;
1980 data->id = id->driver_data;
1981 data->chip_spec = &vcnl4000_chip_spec_cfg[data->id];
1982
1983 mutex_init(&data->vcnl4000_lock);
1984
1985 ret = data->chip_spec->init(data);
1986 if (ret < 0)
1987 return ret;
1988
1989 dev_dbg(&client->dev, "%s Ambient light/proximity sensor, Rev: %02x\n",
1990 data->chip_spec->prod, data->rev);
1991
1992 if (device_property_read_u32(&client->dev, "proximity-near-level",
1993 &data->near_level))
1994 data->near_level = 0;
1995
1996 indio_dev->info = data->chip_spec->info;
1997 indio_dev->channels = data->chip_spec->channels;
1998 indio_dev->num_channels = data->chip_spec->num_channels;
1999 indio_dev->name = VCNL4000_DRV_NAME;
2000 indio_dev->modes = INDIO_DIRECT_MODE;
2001
2002 if (data->chip_spec->trig_buffer_func &&
2003 data->chip_spec->buffer_setup_ops) {
2004 ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev,
2005 NULL,
2006 data->chip_spec->trig_buffer_func,
2007 data->chip_spec->buffer_setup_ops);
2008 if (ret < 0) {
2009 dev_err(&client->dev,
2010 "unable to setup iio triggered buffer\n");
2011 return ret;
2012 }
2013 }
2014
2015 if (client->irq && data->chip_spec->irq_thread) {
2016 ret = devm_request_threaded_irq(&client->dev, client->irq,
2017 NULL, data->chip_spec->irq_thread,
2018 IRQF_TRIGGER_FALLING |
2019 IRQF_ONESHOT,
2020 "vcnl4000_irq",
2021 indio_dev);
2022 if (ret < 0) {
2023 dev_err(&client->dev, "irq request failed\n");
2024 return ret;
2025 }
2026
2027 ret = vcnl4010_probe_trigger(indio_dev);
2028 if (ret < 0)
2029 return ret;
2030 }
2031
2032 ret = pm_runtime_set_active(&client->dev);
2033 if (ret < 0)
2034 goto fail_poweroff;
2035
2036 ret = iio_device_register(indio_dev);
2037 if (ret < 0)
2038 goto fail_poweroff;
2039
2040 pm_runtime_enable(&client->dev);
2041 pm_runtime_set_autosuspend_delay(&client->dev, VCNL4000_SLEEP_DELAY_MS);
2042 pm_runtime_use_autosuspend(&client->dev);
2043
2044 return 0;
2045 fail_poweroff:
2046 data->chip_spec->set_power_state(data, false);
2047 return ret;
2048 }
2049
2050 static const struct of_device_id vcnl_4000_of_match[] = {
2051 {
2052 .compatible = "vishay,vcnl4000",
2053 .data = (void *)VCNL4000,
2054 },
2055 {
2056 .compatible = "vishay,vcnl4010",
2057 .data = (void *)VCNL4010,
2058 },
2059 {
2060 .compatible = "vishay,vcnl4020",
2061 .data = (void *)VCNL4010,
2062 },
2063 {
2064 .compatible = "vishay,vcnl4040",
2065 .data = (void *)VCNL4040,
2066 },
2067 {
2068 .compatible = "vishay,vcnl4200",
2069 .data = (void *)VCNL4200,
2070 },
2071 { }
2072 };
2073 MODULE_DEVICE_TABLE(of, vcnl_4000_of_match);
2074
vcnl4000_remove(struct i2c_client * client)2075 static void vcnl4000_remove(struct i2c_client *client)
2076 {
2077 struct iio_dev *indio_dev = i2c_get_clientdata(client);
2078 struct vcnl4000_data *data = iio_priv(indio_dev);
2079 int ret;
2080
2081 pm_runtime_dont_use_autosuspend(&client->dev);
2082 pm_runtime_disable(&client->dev);
2083 iio_device_unregister(indio_dev);
2084 pm_runtime_set_suspended(&client->dev);
2085
2086 ret = data->chip_spec->set_power_state(data, false);
2087 if (ret)
2088 dev_warn(&client->dev, "Failed to power down (%pe)\n",
2089 ERR_PTR(ret));
2090 }
2091
vcnl4000_runtime_suspend(struct device * dev)2092 static int vcnl4000_runtime_suspend(struct device *dev)
2093 {
2094 struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
2095 struct vcnl4000_data *data = iio_priv(indio_dev);
2096
2097 return data->chip_spec->set_power_state(data, false);
2098 }
2099
vcnl4000_runtime_resume(struct device * dev)2100 static int vcnl4000_runtime_resume(struct device *dev)
2101 {
2102 struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
2103 struct vcnl4000_data *data = iio_priv(indio_dev);
2104
2105 return data->chip_spec->set_power_state(data, true);
2106 }
2107
2108 static DEFINE_RUNTIME_DEV_PM_OPS(vcnl4000_pm_ops, vcnl4000_runtime_suspend,
2109 vcnl4000_runtime_resume, NULL);
2110
2111 static struct i2c_driver vcnl4000_driver = {
2112 .driver = {
2113 .name = VCNL4000_DRV_NAME,
2114 .pm = pm_ptr(&vcnl4000_pm_ops),
2115 .of_match_table = vcnl_4000_of_match,
2116 },
2117 .probe = vcnl4000_probe,
2118 .id_table = vcnl4000_id,
2119 .remove = vcnl4000_remove,
2120 };
2121
2122 module_i2c_driver(vcnl4000_driver);
2123
2124 MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
2125 MODULE_AUTHOR("Mathieu Othacehe <m.othacehe@gmail.com>");
2126 MODULE_DESCRIPTION("Vishay VCNL4000 proximity/ambient light sensor driver");
2127 MODULE_LICENSE("GPL");
2128