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