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
125static 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
136static 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
147static 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
156static const int vcnl4040_als_it_times[][2] = {
157 {0, 80000},
158 {0, 160000},
159 {0, 320000},
160 {0, 640000},
161};
162
163static const int vcnl4200_als_it_times[][2] = {
164 {0, 50000},
165 {0, 100000},
166 {0, 200000},
167 {0, 400000},
168};
169
170static 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
181static const int vcnl4040_als_persistence[] = {1, 2, 4, 8};
182static const int vcnl4040_ps_persistence[] = {1, 2, 3, 4};
183static 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
187enum vcnl4000_device_ids {
188 VCNL4000,
189 VCNL4010,
190 VCNL4040,
191 VCNL4200,
192};
193
194struct vcnl4200_channel {
195 u8 reg;
196 ktime_t last_measurement;
197 ktime_t sampling_rate;
198 struct mutex lock;
199};
200
201struct 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
216struct 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
237static const struct i2c_device_id vcnl4000_id[] = {
238 { "vcnl4000", VCNL4000 },
239 { "vcnl4010", VCNL4010 },
240 { "vcnl4020", VCNL4010 },
241 { "vcnl4040", VCNL4040 },
242 { "vcnl4200", VCNL4200 },
243 { }
244};
245MODULE_DEVICE_TABLE(i2c, vcnl4000_id);
246
247static int vcnl4000_set_power_state(struct vcnl4000_data *data, bool on)
248{
249 /* no suspend op */
250 return 0;
251}
252
253static int vcnl4000_init(struct vcnl4000_data *data)
254{
255 int ret, prod_id;
256
257 ret = i2c_smbus_read_byte_data(client: 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
283static 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(client: 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(client: data->client, VCNL4200_AL_CONF, value: ret);
299
300out:
301 mutex_unlock(lock: &data->vcnl4000_lock);
302
303 return ret;
304}
305
306static 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(client: 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(client: data->client, VCNL4200_PS_CONF1, value: ret);
322
323out:
324 mutex_unlock(lock: &data->vcnl4000_lock);
325
326 return ret;
327}
328
329static 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, en: on);
338 if (ret < 0)
339 return ret;
340
341 ret = vcnl4000_write_ps_enable(data, en: 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
354static int vcnl4200_init(struct vcnl4000_data *data)
355{
356 int ret, id;
357 u16 regval;
358
359 ret = i2c_smbus_read_word_data(client: 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(client: 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(secs: 0, nsecs: 60000 * 1000);
388 /* Default wait time is 4.8ms, add 20% tolerance. */
389 data->vcnl4200_ps.sampling_rate = ktime_set(secs: 0, nsecs: 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(secs: 0, nsecs: 96000 * 1000);
394 /* Default wait time is 5ms, add 20% tolerance. */
395 data->vcnl4200_ps.sampling_rate = ktime_set(secs: 0, nsecs: 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(client: 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(client: data->client, VCNL4200_PS_CONF1,
410 value: 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(client: 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(client: data->client, VCNL4200_PS_CONF3,
421 value: 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
432static 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(client: data->client, command: data_reg);
437 if (ret < 0)
438 return ret;
439
440 *val = ret;
441 return 0;
442}
443
444static 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(client: data->client, command: data_reg, value: val);
450}
451
452
453static 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(client: data->client, VCNL4000_COMMAND,
462 value: 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(client: data->client, VCNL4000_COMMAND);
469 if (ret < 0)
470 goto fail;
471 if (ret & rdy_mask)
472 break;
473 msleep(msecs: 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(lock: &data->vcnl4000_lock);
488
489 return 0;
490
491fail:
492 mutex_unlock(lock: &data->vcnl4000_lock);
493 return ret;
494}
495
496static 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(later: next_measurement, earlier: ktime_get());
508 if (delta > 0)
509 usleep_range(min: delta, max: delta + 500);
510 chan->last_measurement = ktime_get();
511
512 mutex_unlock(lock: &chan->lock);
513
514 ret = i2c_smbus_read_word_data(client: data->client, command: chan->reg);
515 if (ret < 0)
516 return ret;
517
518 *val = ret;
519
520 return 0;
521}
522
523static 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
530static int vcnl4200_measure_light(struct vcnl4000_data *data, int *val)
531{
532 return vcnl4200_measure(data, chan: &data->vcnl4200_al, val);
533}
534
535static 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
542static int vcnl4200_measure_proximity(struct vcnl4000_data *data, int *val)
543{
544 return vcnl4200_measure(data, chan: &data->vcnl4200_ps, val);
545}
546
547static 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(client: 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
565static bool vcnl4010_is_in_periodic_mode(struct vcnl4000_data *data)
566{
567 int ret;
568
569 ret = i2c_smbus_read_byte_data(client: data->client, VCNL4000_COMMAND);
570 if (ret < 0)
571 return false;
572
573 return !!(ret & VCNL4000_SELF_TIMED_EN);
574}
575
576static 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
591static 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(client: 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
609static 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(secs: 0, nsecs: val * 1200);
624 data->al_scale = div_u64(dividend: mul_u32_u32(a: data->chip_spec->ulux_step,
625 b: (*data->chip_spec->als_it_times)[0][1]),
626 divisor: val);
627
628 mutex_lock(&data->vcnl4000_lock);
629
630 ret = i2c_smbus_read_word_data(client: 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(client: data->client,
637 VCNL4200_AL_CONF,
638 value: regval);
639
640out_unlock:
641 mutex_unlock(lock: &data->vcnl4000_lock);
642 return ret;
643}
644
645static 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(client: 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
664static 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(secs: 0, nsecs: val * 60 * NSEC_PER_USEC);
681
682 mutex_lock(&data->vcnl4000_lock);
683
684 ret = i2c_smbus_read_word_data(client: 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(client: data->client, VCNL4200_PS_CONF1,
691 value: regval);
692
693out:
694 mutex_unlock(lock: &data->vcnl4000_lock);
695 return ret;
696}
697
698static 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(client: 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(a: (*data->chip_spec->als_it_times)[it][1],
716 b: vcnl4040_als_persistence[ret_pers]);
717 *val = div_u64_rem(dividend: val_c, MICRO, remainder: val2);
718
719 return IIO_VAL_INT_PLUS_MICRO;
720}
721
722static 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(a: val, MICRO) + val2;
728
729 ret = i2c_smbus_read_word_data(client: 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(a: vcnl4040_als_persistence[i],
739 b: (*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(client: 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(client: data->client, VCNL4200_AL_CONF,
752 value: regval);
753
754out_unlock:
755 mutex_unlock(lock: &data->vcnl4000_lock);
756 return ret;
757}
758
759static 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(client: 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
782static 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(client: 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(client: 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(client: data->client, VCNL4200_PS_CONF1,
814 value: regval);
815
816out_unlock:
817 mutex_unlock(lock: &data->vcnl4000_lock);
818 return ret;
819}
820
821static 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(client: 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
838static 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(client: 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(client: data->client, VCNL4200_PS_CONF3,
861 value: regval);
862
863out_unlock:
864 mutex_unlock(lock: &data->vcnl4000_lock);
865 return ret;
866}
867
868static 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(client: 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
886static 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(client: 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(client: data->client, VCNL4200_PS_CONF3,
909 value: regval);
910
911out_unlock:
912 mutex_unlock(lock: &data->vcnl4000_lock);
913 return ret;
914}
915
916static 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, on: 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, on: 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
992static 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, val: val2);
1005 case IIO_PROXIMITY:
1006 return vcnl4040_write_ps_it(data, val: 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, val: val2);
1021 default:
1022 return -EINVAL;
1023 }
1024 default:
1025 return -EINVAL;
1026 }
1027}
1028
1029static 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
1077static 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 ret = iio_device_claim_direct_mode(indio_dev);
1088 if (ret)
1089 return ret;
1090
1091 /* Protect against event capture. */
1092 if (vcnl4010_is_in_periodic_mode(data)) {
1093 ret = -EBUSY;
1094 } else {
1095 ret = vcnl4000_read_raw(indio_dev, chan, val, val2,
1096 mask);
1097 }
1098
1099 iio_device_release_direct_mode(indio_dev);
1100 return ret;
1101 case IIO_CHAN_INFO_SAMP_FREQ:
1102 switch (chan->type) {
1103 case IIO_PROXIMITY:
1104 ret = vcnl4010_read_proxy_samp_freq(data, val, val2);
1105 if (ret < 0)
1106 return ret;
1107 return IIO_VAL_INT_PLUS_MICRO;
1108 default:
1109 return -EINVAL;
1110 }
1111 default:
1112 return -EINVAL;
1113 }
1114}
1115
1116static int vcnl4010_read_avail(struct iio_dev *indio_dev,
1117 struct iio_chan_spec const *chan,
1118 const int **vals, int *type, int *length,
1119 long mask)
1120{
1121 switch (mask) {
1122 case IIO_CHAN_INFO_SAMP_FREQ:
1123 *vals = (int *)vcnl4010_prox_sampling_frequency;
1124 *type = IIO_VAL_INT_PLUS_MICRO;
1125 *length = 2 * ARRAY_SIZE(vcnl4010_prox_sampling_frequency);
1126 return IIO_AVAIL_LIST;
1127 default:
1128 return -EINVAL;
1129 }
1130}
1131
1132static int vcnl4010_write_proxy_samp_freq(struct vcnl4000_data *data, int val,
1133 int val2)
1134{
1135 unsigned int i;
1136 int index = -1;
1137
1138 for (i = 0; i < ARRAY_SIZE(vcnl4010_prox_sampling_frequency); i++) {
1139 if (val == vcnl4010_prox_sampling_frequency[i][0] &&
1140 val2 == vcnl4010_prox_sampling_frequency[i][1]) {
1141 index = i;
1142 break;
1143 }
1144 }
1145
1146 if (index < 0)
1147 return -EINVAL;
1148
1149 return i2c_smbus_write_byte_data(client: data->client, VCNL4010_PROX_RATE,
1150 value: index);
1151}
1152
1153static int vcnl4010_write_raw(struct iio_dev *indio_dev,
1154 struct iio_chan_spec const *chan,
1155 int val, int val2, long mask)
1156{
1157 int ret;
1158 struct vcnl4000_data *data = iio_priv(indio_dev);
1159
1160 ret = iio_device_claim_direct_mode(indio_dev);
1161 if (ret)
1162 return ret;
1163
1164 /* Protect against event capture. */
1165 if (vcnl4010_is_in_periodic_mode(data)) {
1166 ret = -EBUSY;
1167 goto end;
1168 }
1169
1170 switch (mask) {
1171 case IIO_CHAN_INFO_SAMP_FREQ:
1172 switch (chan->type) {
1173 case IIO_PROXIMITY:
1174 ret = vcnl4010_write_proxy_samp_freq(data, val, val2);
1175 goto end;
1176 default:
1177 ret = -EINVAL;
1178 goto end;
1179 }
1180 default:
1181 ret = -EINVAL;
1182 goto end;
1183 }
1184
1185end:
1186 iio_device_release_direct_mode(indio_dev);
1187 return ret;
1188}
1189
1190static int vcnl4010_read_event(struct iio_dev *indio_dev,
1191 const struct iio_chan_spec *chan,
1192 enum iio_event_type type,
1193 enum iio_event_direction dir,
1194 enum iio_event_info info,
1195 int *val, int *val2)
1196{
1197 int ret;
1198 struct vcnl4000_data *data = iio_priv(indio_dev);
1199
1200 switch (info) {
1201 case IIO_EV_INFO_VALUE:
1202 switch (dir) {
1203 case IIO_EV_DIR_RISING:
1204 ret = vcnl4000_read_data(data, VCNL4010_HIGH_THR_HI,
1205 val);
1206 if (ret < 0)
1207 return ret;
1208 return IIO_VAL_INT;
1209 case IIO_EV_DIR_FALLING:
1210 ret = vcnl4000_read_data(data, VCNL4010_LOW_THR_HI,
1211 val);
1212 if (ret < 0)
1213 return ret;
1214 return IIO_VAL_INT;
1215 default:
1216 return -EINVAL;
1217 }
1218 default:
1219 return -EINVAL;
1220 }
1221}
1222
1223static int vcnl4010_write_event(struct iio_dev *indio_dev,
1224 const struct iio_chan_spec *chan,
1225 enum iio_event_type type,
1226 enum iio_event_direction dir,
1227 enum iio_event_info info,
1228 int val, int val2)
1229{
1230 int ret;
1231 struct vcnl4000_data *data = iio_priv(indio_dev);
1232
1233 switch (info) {
1234 case IIO_EV_INFO_VALUE:
1235 switch (dir) {
1236 case IIO_EV_DIR_RISING:
1237 ret = vcnl4000_write_data(data, VCNL4010_HIGH_THR_HI,
1238 val);
1239 if (ret < 0)
1240 return ret;
1241 return IIO_VAL_INT;
1242 case IIO_EV_DIR_FALLING:
1243 ret = vcnl4000_write_data(data, VCNL4010_LOW_THR_HI,
1244 val);
1245 if (ret < 0)
1246 return ret;
1247 return IIO_VAL_INT;
1248 default:
1249 return -EINVAL;
1250 }
1251 default:
1252 return -EINVAL;
1253 }
1254}
1255
1256static int vcnl4040_read_event(struct iio_dev *indio_dev,
1257 const struct iio_chan_spec *chan,
1258 enum iio_event_type type,
1259 enum iio_event_direction dir,
1260 enum iio_event_info info,
1261 int *val, int *val2)
1262{
1263 int ret;
1264 struct vcnl4000_data *data = iio_priv(indio_dev);
1265
1266 switch (chan->type) {
1267 case IIO_LIGHT:
1268 switch (info) {
1269 case IIO_EV_INFO_PERIOD:
1270 return vcnl4040_read_als_period(data, val, val2);
1271 case IIO_EV_INFO_VALUE:
1272 switch (dir) {
1273 case IIO_EV_DIR_RISING:
1274 ret = i2c_smbus_read_word_data(client: data->client,
1275 VCNL4040_ALS_THDH_LM);
1276 break;
1277 case IIO_EV_DIR_FALLING:
1278 ret = i2c_smbus_read_word_data(client: data->client,
1279 VCNL4040_ALS_THDL_LM);
1280 break;
1281 default:
1282 return -EINVAL;
1283 }
1284 break;
1285 default:
1286 return -EINVAL;
1287 }
1288 break;
1289 case IIO_PROXIMITY:
1290 switch (info) {
1291 case IIO_EV_INFO_PERIOD:
1292 return vcnl4040_read_ps_period(data, val, val2);
1293 case IIO_EV_INFO_VALUE:
1294 switch (dir) {
1295 case IIO_EV_DIR_RISING:
1296 ret = i2c_smbus_read_word_data(client: data->client,
1297 VCNL4040_PS_THDH_LM);
1298 break;
1299 case IIO_EV_DIR_FALLING:
1300 ret = i2c_smbus_read_word_data(client: data->client,
1301 VCNL4040_PS_THDL_LM);
1302 break;
1303 default:
1304 return -EINVAL;
1305 }
1306 break;
1307 default:
1308 return -EINVAL;
1309 }
1310 break;
1311 default:
1312 return -EINVAL;
1313 }
1314 if (ret < 0)
1315 return ret;
1316 *val = ret;
1317 return IIO_VAL_INT;
1318}
1319
1320static int vcnl4040_write_event(struct iio_dev *indio_dev,
1321 const struct iio_chan_spec *chan,
1322 enum iio_event_type type,
1323 enum iio_event_direction dir,
1324 enum iio_event_info info,
1325 int val, int val2)
1326{
1327 int ret;
1328 struct vcnl4000_data *data = iio_priv(indio_dev);
1329
1330 switch (chan->type) {
1331 case IIO_LIGHT:
1332 switch (info) {
1333 case IIO_EV_INFO_PERIOD:
1334 return vcnl4040_write_als_period(data, val, val2);
1335 case IIO_EV_INFO_VALUE:
1336 switch (dir) {
1337 case IIO_EV_DIR_RISING:
1338 ret = i2c_smbus_write_word_data(client: data->client,
1339 VCNL4040_ALS_THDH_LM,
1340 value: val);
1341 break;
1342 case IIO_EV_DIR_FALLING:
1343 ret = i2c_smbus_write_word_data(client: data->client,
1344 VCNL4040_ALS_THDL_LM,
1345 value: val);
1346 break;
1347 default:
1348 return -EINVAL;
1349 }
1350 break;
1351 default:
1352 return -EINVAL;
1353 }
1354 break;
1355 case IIO_PROXIMITY:
1356 switch (info) {
1357 case IIO_EV_INFO_PERIOD:
1358 return vcnl4040_write_ps_period(data, val, val2);
1359 case IIO_EV_INFO_VALUE:
1360 switch (dir) {
1361 case IIO_EV_DIR_RISING:
1362 ret = i2c_smbus_write_word_data(client: data->client,
1363 VCNL4040_PS_THDH_LM,
1364 value: val);
1365 break;
1366 case IIO_EV_DIR_FALLING:
1367 ret = i2c_smbus_write_word_data(client: data->client,
1368 VCNL4040_PS_THDL_LM,
1369 value: val);
1370 break;
1371 default:
1372 return -EINVAL;
1373 }
1374 break;
1375 default:
1376 return -EINVAL;
1377 }
1378 break;
1379 default:
1380 return -EINVAL;
1381 }
1382 if (ret < 0)
1383 return ret;
1384 return IIO_VAL_INT;
1385}
1386
1387static bool vcnl4010_is_thr_enabled(struct vcnl4000_data *data)
1388{
1389 int ret;
1390
1391 ret = i2c_smbus_read_byte_data(client: data->client, VCNL4010_INT_CTRL);
1392 if (ret < 0)
1393 return false;
1394
1395 return !!(ret & VCNL4010_INT_THR_EN);
1396}
1397
1398static int vcnl4010_read_event_config(struct iio_dev *indio_dev,
1399 const struct iio_chan_spec *chan,
1400 enum iio_event_type type,
1401 enum iio_event_direction dir)
1402{
1403 struct vcnl4000_data *data = iio_priv(indio_dev);
1404
1405 switch (chan->type) {
1406 case IIO_PROXIMITY:
1407 return vcnl4010_is_thr_enabled(data);
1408 default:
1409 return -EINVAL;
1410 }
1411}
1412
1413static int vcnl4010_config_threshold(struct iio_dev *indio_dev, bool state)
1414{
1415 struct vcnl4000_data *data = iio_priv(indio_dev);
1416 int ret;
1417 int icr;
1418 int command;
1419
1420 if (state) {
1421 ret = iio_device_claim_direct_mode(indio_dev);
1422 if (ret)
1423 return ret;
1424
1425 /* Enable periodic measurement of proximity data. */
1426 command = VCNL4000_SELF_TIMED_EN | VCNL4000_PROX_EN;
1427
1428 /*
1429 * Enable interrupts on threshold, for proximity data by
1430 * default.
1431 */
1432 icr = VCNL4010_INT_THR_EN;
1433 } else {
1434 if (!vcnl4010_is_thr_enabled(data))
1435 return 0;
1436
1437 command = 0;
1438 icr = 0;
1439 }
1440
1441 ret = i2c_smbus_write_byte_data(client: data->client, VCNL4000_COMMAND,
1442 value: command);
1443 if (ret < 0)
1444 goto end;
1445
1446 ret = i2c_smbus_write_byte_data(client: data->client, VCNL4010_INT_CTRL, value: icr);
1447
1448end:
1449 if (state)
1450 iio_device_release_direct_mode(indio_dev);
1451
1452 return ret;
1453}
1454
1455static int vcnl4010_write_event_config(struct iio_dev *indio_dev,
1456 const struct iio_chan_spec *chan,
1457 enum iio_event_type type,
1458 enum iio_event_direction dir,
1459 int state)
1460{
1461 switch (chan->type) {
1462 case IIO_PROXIMITY:
1463 return vcnl4010_config_threshold(indio_dev, state);
1464 default:
1465 return -EINVAL;
1466 }
1467}
1468
1469static int vcnl4040_read_event_config(struct iio_dev *indio_dev,
1470 const struct iio_chan_spec *chan,
1471 enum iio_event_type type,
1472 enum iio_event_direction dir)
1473{
1474 int ret;
1475 struct vcnl4000_data *data = iio_priv(indio_dev);
1476
1477 switch (chan->type) {
1478 case IIO_LIGHT:
1479 ret = i2c_smbus_read_word_data(client: data->client, VCNL4200_AL_CONF);
1480 if (ret < 0)
1481 return ret;
1482
1483 data->als_int = FIELD_GET(VCNL4040_ALS_CONF_INT_EN, ret);
1484
1485 return data->als_int;
1486 case IIO_PROXIMITY:
1487 ret = i2c_smbus_read_word_data(client: data->client, VCNL4200_PS_CONF1);
1488 if (ret < 0)
1489 return ret;
1490
1491 data->ps_int = FIELD_GET(VCNL4040_PS_CONF2_PS_INT, ret);
1492
1493 return (dir == IIO_EV_DIR_RISING) ?
1494 FIELD_GET(VCNL4040_PS_IF_AWAY, ret) :
1495 FIELD_GET(VCNL4040_PS_IF_CLOSE, ret);
1496 default:
1497 return -EINVAL;
1498 }
1499}
1500
1501static int vcnl4040_write_event_config(struct iio_dev *indio_dev,
1502 const struct iio_chan_spec *chan,
1503 enum iio_event_type type,
1504 enum iio_event_direction dir, int state)
1505{
1506 int ret = -EINVAL;
1507 u16 val, mask;
1508 struct vcnl4000_data *data = iio_priv(indio_dev);
1509
1510 mutex_lock(&data->vcnl4000_lock);
1511
1512 switch (chan->type) {
1513 case IIO_LIGHT:
1514 ret = i2c_smbus_read_word_data(client: data->client, VCNL4200_AL_CONF);
1515 if (ret < 0)
1516 goto out;
1517
1518 mask = VCNL4040_ALS_CONF_INT_EN;
1519 if (state)
1520 val = (ret | mask);
1521 else
1522 val = (ret & ~mask);
1523
1524 data->als_int = FIELD_GET(VCNL4040_ALS_CONF_INT_EN, val);
1525 ret = i2c_smbus_write_word_data(client: data->client, VCNL4200_AL_CONF,
1526 value: val);
1527 break;
1528 case IIO_PROXIMITY:
1529 ret = i2c_smbus_read_word_data(client: data->client, VCNL4200_PS_CONF1);
1530 if (ret < 0)
1531 goto out;
1532
1533 if (dir == IIO_EV_DIR_RISING)
1534 mask = VCNL4040_PS_IF_AWAY;
1535 else
1536 mask = VCNL4040_PS_IF_CLOSE;
1537
1538 val = state ? (ret | mask) : (ret & ~mask);
1539
1540 data->ps_int = FIELD_GET(VCNL4040_PS_CONF2_PS_INT, val);
1541 ret = i2c_smbus_write_word_data(client: data->client, VCNL4200_PS_CONF1,
1542 value: val);
1543 break;
1544 default:
1545 break;
1546 }
1547
1548out:
1549 mutex_unlock(lock: &data->vcnl4000_lock);
1550
1551 return ret;
1552}
1553
1554static irqreturn_t vcnl4040_irq_thread(int irq, void *p)
1555{
1556 struct iio_dev *indio_dev = p;
1557 struct vcnl4000_data *data = iio_priv(indio_dev);
1558 int ret;
1559
1560 ret = i2c_smbus_read_word_data(client: data->client, command: data->chip_spec->int_reg);
1561 if (ret < 0)
1562 return IRQ_HANDLED;
1563
1564 if (ret & VCNL4040_PS_IF_CLOSE) {
1565 iio_push_event(indio_dev,
1566 IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, 0,
1567 IIO_EV_TYPE_THRESH,
1568 IIO_EV_DIR_RISING),
1569 timestamp: iio_get_time_ns(indio_dev));
1570 }
1571
1572 if (ret & VCNL4040_PS_IF_AWAY) {
1573 iio_push_event(indio_dev,
1574 IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, 0,
1575 IIO_EV_TYPE_THRESH,
1576 IIO_EV_DIR_FALLING),
1577 timestamp: iio_get_time_ns(indio_dev));
1578 }
1579
1580 if (ret & VCNL4040_ALS_FALLING) {
1581 iio_push_event(indio_dev,
1582 IIO_UNMOD_EVENT_CODE(IIO_LIGHT, 0,
1583 IIO_EV_TYPE_THRESH,
1584 IIO_EV_DIR_FALLING),
1585 timestamp: iio_get_time_ns(indio_dev));
1586 }
1587
1588 if (ret & VCNL4040_ALS_RISING) {
1589 iio_push_event(indio_dev,
1590 IIO_UNMOD_EVENT_CODE(IIO_LIGHT, 0,
1591 IIO_EV_TYPE_THRESH,
1592 IIO_EV_DIR_RISING),
1593 timestamp: iio_get_time_ns(indio_dev));
1594 }
1595
1596 return IRQ_HANDLED;
1597}
1598
1599static ssize_t vcnl4000_read_near_level(struct iio_dev *indio_dev,
1600 uintptr_t priv,
1601 const struct iio_chan_spec *chan,
1602 char *buf)
1603{
1604 struct vcnl4000_data *data = iio_priv(indio_dev);
1605
1606 return sprintf(buf, fmt: "%u\n", data->near_level);
1607}
1608
1609static irqreturn_t vcnl4010_irq_thread(int irq, void *p)
1610{
1611 struct iio_dev *indio_dev = p;
1612 struct vcnl4000_data *data = iio_priv(indio_dev);
1613 unsigned long isr;
1614 int ret;
1615
1616 ret = i2c_smbus_read_byte_data(client: data->client, VCNL4010_ISR);
1617 if (ret < 0)
1618 goto end;
1619
1620 isr = ret;
1621
1622 if (isr & VCNL4010_INT_THR) {
1623 if (test_bit(VCNL4010_INT_THR_LOW, &isr)) {
1624 iio_push_event(indio_dev,
1625 IIO_UNMOD_EVENT_CODE(
1626 IIO_PROXIMITY,
1627 1,
1628 IIO_EV_TYPE_THRESH,
1629 IIO_EV_DIR_FALLING),
1630 timestamp: iio_get_time_ns(indio_dev));
1631 }
1632
1633 if (test_bit(VCNL4010_INT_THR_HIGH, &isr)) {
1634 iio_push_event(indio_dev,
1635 IIO_UNMOD_EVENT_CODE(
1636 IIO_PROXIMITY,
1637 1,
1638 IIO_EV_TYPE_THRESH,
1639 IIO_EV_DIR_RISING),
1640 timestamp: iio_get_time_ns(indio_dev));
1641 }
1642
1643 i2c_smbus_write_byte_data(client: data->client, VCNL4010_ISR,
1644 value: isr & VCNL4010_INT_THR);
1645 }
1646
1647 if (isr & VCNL4010_INT_DRDY && iio_buffer_enabled(indio_dev))
1648 iio_trigger_poll_nested(trig: indio_dev->trig);
1649
1650end:
1651 return IRQ_HANDLED;
1652}
1653
1654static irqreturn_t vcnl4010_trigger_handler(int irq, void *p)
1655{
1656 struct iio_poll_func *pf = p;
1657 struct iio_dev *indio_dev = pf->indio_dev;
1658 struct vcnl4000_data *data = iio_priv(indio_dev);
1659 const unsigned long *active_scan_mask = indio_dev->active_scan_mask;
1660 u16 buffer[8] __aligned(8) = {0}; /* 1x16-bit + naturally aligned ts */
1661 bool data_read = false;
1662 unsigned long isr;
1663 int val = 0;
1664 int ret;
1665
1666 ret = i2c_smbus_read_byte_data(client: data->client, VCNL4010_ISR);
1667 if (ret < 0)
1668 goto end;
1669
1670 isr = ret;
1671
1672 if (test_bit(0, active_scan_mask)) {
1673 if (test_bit(VCNL4010_INT_PROXIMITY, &isr)) {
1674 ret = vcnl4000_read_data(data,
1675 VCNL4000_PS_RESULT_HI,
1676 val: &val);
1677 if (ret < 0)
1678 goto end;
1679
1680 buffer[0] = val;
1681 data_read = true;
1682 }
1683 }
1684
1685 ret = i2c_smbus_write_byte_data(client: data->client, VCNL4010_ISR,
1686 value: isr & VCNL4010_INT_DRDY);
1687 if (ret < 0)
1688 goto end;
1689
1690 if (!data_read)
1691 goto end;
1692
1693 iio_push_to_buffers_with_timestamp(indio_dev, data: buffer,
1694 timestamp: iio_get_time_ns(indio_dev));
1695
1696end:
1697 iio_trigger_notify_done(trig: indio_dev->trig);
1698 return IRQ_HANDLED;
1699}
1700
1701static int vcnl4010_buffer_postenable(struct iio_dev *indio_dev)
1702{
1703 struct vcnl4000_data *data = iio_priv(indio_dev);
1704 int ret;
1705 int cmd;
1706
1707 /* Do not enable the buffer if we are already capturing events. */
1708 if (vcnl4010_is_in_periodic_mode(data))
1709 return -EBUSY;
1710
1711 ret = i2c_smbus_write_byte_data(client: data->client, VCNL4010_INT_CTRL,
1712 VCNL4010_INT_PROX_EN);
1713 if (ret < 0)
1714 return ret;
1715
1716 cmd = VCNL4000_SELF_TIMED_EN | VCNL4000_PROX_EN;
1717 return i2c_smbus_write_byte_data(client: data->client, VCNL4000_COMMAND, value: cmd);
1718}
1719
1720static int vcnl4010_buffer_predisable(struct iio_dev *indio_dev)
1721{
1722 struct vcnl4000_data *data = iio_priv(indio_dev);
1723 int ret;
1724
1725 ret = i2c_smbus_write_byte_data(client: data->client, VCNL4010_INT_CTRL, value: 0);
1726 if (ret < 0)
1727 return ret;
1728
1729 return i2c_smbus_write_byte_data(client: data->client, VCNL4000_COMMAND, value: 0);
1730}
1731
1732static const struct iio_buffer_setup_ops vcnl4010_buffer_ops = {
1733 .postenable = &vcnl4010_buffer_postenable,
1734 .predisable = &vcnl4010_buffer_predisable,
1735};
1736
1737static const struct iio_chan_spec_ext_info vcnl4000_ext_info[] = {
1738 {
1739 .name = "nearlevel",
1740 .shared = IIO_SEPARATE,
1741 .read = vcnl4000_read_near_level,
1742 },
1743 { /* sentinel */ }
1744};
1745
1746static const struct iio_event_spec vcnl4000_event_spec[] = {
1747 {
1748 .type = IIO_EV_TYPE_THRESH,
1749 .dir = IIO_EV_DIR_RISING,
1750 .mask_separate = BIT(IIO_EV_INFO_VALUE),
1751 }, {
1752 .type = IIO_EV_TYPE_THRESH,
1753 .dir = IIO_EV_DIR_FALLING,
1754 .mask_separate = BIT(IIO_EV_INFO_VALUE),
1755 }, {
1756 .type = IIO_EV_TYPE_THRESH,
1757 .dir = IIO_EV_DIR_EITHER,
1758 .mask_separate = BIT(IIO_EV_INFO_ENABLE),
1759 }
1760};
1761
1762static const struct iio_event_spec vcnl4040_als_event_spec[] = {
1763 {
1764 .type = IIO_EV_TYPE_THRESH,
1765 .dir = IIO_EV_DIR_RISING,
1766 .mask_separate = BIT(IIO_EV_INFO_VALUE),
1767 }, {
1768 .type = IIO_EV_TYPE_THRESH,
1769 .dir = IIO_EV_DIR_FALLING,
1770 .mask_separate = BIT(IIO_EV_INFO_VALUE),
1771 }, {
1772 .type = IIO_EV_TYPE_THRESH,
1773 .dir = IIO_EV_DIR_EITHER,
1774 .mask_separate = BIT(IIO_EV_INFO_ENABLE) | BIT(IIO_EV_INFO_PERIOD),
1775 },
1776};
1777
1778static const struct iio_event_spec vcnl4040_event_spec[] = {
1779 {
1780 .type = IIO_EV_TYPE_THRESH,
1781 .dir = IIO_EV_DIR_RISING,
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_FALLING,
1786 .mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE),
1787 }, {
1788 .type = IIO_EV_TYPE_THRESH,
1789 .dir = IIO_EV_DIR_EITHER,
1790 .mask_separate = BIT(IIO_EV_INFO_PERIOD),
1791 },
1792};
1793
1794static const struct iio_chan_spec vcnl4000_channels[] = {
1795 {
1796 .type = IIO_LIGHT,
1797 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
1798 BIT(IIO_CHAN_INFO_SCALE),
1799 }, {
1800 .type = IIO_PROXIMITY,
1801 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
1802 .ext_info = vcnl4000_ext_info,
1803 }
1804};
1805
1806static const struct iio_chan_spec vcnl4010_channels[] = {
1807 {
1808 .type = IIO_LIGHT,
1809 .scan_index = -1,
1810 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
1811 BIT(IIO_CHAN_INFO_SCALE),
1812 }, {
1813 .type = IIO_PROXIMITY,
1814 .scan_index = 0,
1815 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
1816 BIT(IIO_CHAN_INFO_SAMP_FREQ),
1817 .info_mask_separate_available = BIT(IIO_CHAN_INFO_SAMP_FREQ),
1818 .event_spec = vcnl4000_event_spec,
1819 .num_event_specs = ARRAY_SIZE(vcnl4000_event_spec),
1820 .ext_info = vcnl4000_ext_info,
1821 .scan_type = {
1822 .sign = 'u',
1823 .realbits = 16,
1824 .storagebits = 16,
1825 .endianness = IIO_CPU,
1826 },
1827 },
1828 IIO_CHAN_SOFT_TIMESTAMP(1),
1829};
1830
1831static const struct iio_chan_spec vcnl4040_channels[] = {
1832 {
1833 .type = IIO_LIGHT,
1834 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
1835 BIT(IIO_CHAN_INFO_SCALE) |
1836 BIT(IIO_CHAN_INFO_INT_TIME),
1837 .info_mask_separate_available = BIT(IIO_CHAN_INFO_INT_TIME),
1838 .event_spec = vcnl4040_als_event_spec,
1839 .num_event_specs = ARRAY_SIZE(vcnl4040_als_event_spec),
1840 }, {
1841 .type = IIO_PROXIMITY,
1842 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
1843 BIT(IIO_CHAN_INFO_INT_TIME) |
1844 BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO) |
1845 BIT(IIO_CHAN_INFO_CALIBBIAS),
1846 .info_mask_separate_available = BIT(IIO_CHAN_INFO_INT_TIME) |
1847 BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO) |
1848 BIT(IIO_CHAN_INFO_CALIBBIAS),
1849 .ext_info = vcnl4000_ext_info,
1850 .event_spec = vcnl4040_event_spec,
1851 .num_event_specs = ARRAY_SIZE(vcnl4040_event_spec),
1852 }
1853};
1854
1855static const struct iio_info vcnl4000_info = {
1856 .read_raw = vcnl4000_read_raw,
1857};
1858
1859static const struct iio_info vcnl4010_info = {
1860 .read_raw = vcnl4010_read_raw,
1861 .read_avail = vcnl4010_read_avail,
1862 .write_raw = vcnl4010_write_raw,
1863 .read_event_value = vcnl4010_read_event,
1864 .write_event_value = vcnl4010_write_event,
1865 .read_event_config = vcnl4010_read_event_config,
1866 .write_event_config = vcnl4010_write_event_config,
1867};
1868
1869static const struct iio_info vcnl4040_info = {
1870 .read_raw = vcnl4000_read_raw,
1871 .write_raw = vcnl4040_write_raw,
1872 .read_event_value = vcnl4040_read_event,
1873 .write_event_value = vcnl4040_write_event,
1874 .read_event_config = vcnl4040_read_event_config,
1875 .write_event_config = vcnl4040_write_event_config,
1876 .read_avail = vcnl4040_read_avail,
1877};
1878
1879static const struct vcnl4000_chip_spec vcnl4000_chip_spec_cfg[] = {
1880 [VCNL4000] = {
1881 .prod = "VCNL4000",
1882 .init = vcnl4000_init,
1883 .measure_light = vcnl4000_measure_light,
1884 .measure_proximity = vcnl4000_measure_proximity,
1885 .set_power_state = vcnl4000_set_power_state,
1886 .channels = vcnl4000_channels,
1887 .num_channels = ARRAY_SIZE(vcnl4000_channels),
1888 .info = &vcnl4000_info,
1889 },
1890 [VCNL4010] = {
1891 .prod = "VCNL4010/4020",
1892 .init = vcnl4000_init,
1893 .measure_light = vcnl4000_measure_light,
1894 .measure_proximity = vcnl4000_measure_proximity,
1895 .set_power_state = vcnl4000_set_power_state,
1896 .channels = vcnl4010_channels,
1897 .num_channels = ARRAY_SIZE(vcnl4010_channels),
1898 .info = &vcnl4010_info,
1899 .irq_thread = vcnl4010_irq_thread,
1900 .trig_buffer_func = vcnl4010_trigger_handler,
1901 .buffer_setup_ops = &vcnl4010_buffer_ops,
1902 },
1903 [VCNL4040] = {
1904 .prod = "VCNL4040",
1905 .init = vcnl4200_init,
1906 .measure_light = vcnl4200_measure_light,
1907 .measure_proximity = vcnl4200_measure_proximity,
1908 .set_power_state = vcnl4200_set_power_state,
1909 .channels = vcnl4040_channels,
1910 .num_channels = ARRAY_SIZE(vcnl4040_channels),
1911 .info = &vcnl4040_info,
1912 .irq_thread = vcnl4040_irq_thread,
1913 .int_reg = VCNL4040_INT_FLAGS,
1914 .ps_it_times = &vcnl4040_ps_it_times,
1915 .num_ps_it_times = ARRAY_SIZE(vcnl4040_ps_it_times),
1916 .als_it_times = &vcnl4040_als_it_times,
1917 .num_als_it_times = ARRAY_SIZE(vcnl4040_als_it_times),
1918 .ulux_step = 100000,
1919 },
1920 [VCNL4200] = {
1921 .prod = "VCNL4200",
1922 .init = vcnl4200_init,
1923 .measure_light = vcnl4200_measure_light,
1924 .measure_proximity = vcnl4200_measure_proximity,
1925 .set_power_state = vcnl4200_set_power_state,
1926 .channels = vcnl4040_channels,
1927 .num_channels = ARRAY_SIZE(vcnl4000_channels),
1928 .info = &vcnl4040_info,
1929 .irq_thread = vcnl4040_irq_thread,
1930 .int_reg = VCNL4200_INT_FLAGS,
1931 .ps_it_times = &vcnl4200_ps_it_times,
1932 .num_ps_it_times = ARRAY_SIZE(vcnl4200_ps_it_times),
1933 .als_it_times = &vcnl4200_als_it_times,
1934 .num_als_it_times = ARRAY_SIZE(vcnl4200_als_it_times),
1935 .ulux_step = 24000,
1936 },
1937};
1938
1939static const struct iio_trigger_ops vcnl4010_trigger_ops = {
1940 .validate_device = iio_trigger_validate_own_device,
1941};
1942
1943static int vcnl4010_probe_trigger(struct iio_dev *indio_dev)
1944{
1945 struct vcnl4000_data *data = iio_priv(indio_dev);
1946 struct i2c_client *client = data->client;
1947 struct iio_trigger *trigger;
1948
1949 trigger = devm_iio_trigger_alloc(&client->dev, "%s-dev%d",
1950 indio_dev->name,
1951 iio_device_id(indio_dev));
1952 if (!trigger)
1953 return -ENOMEM;
1954
1955 trigger->ops = &vcnl4010_trigger_ops;
1956 iio_trigger_set_drvdata(trig: trigger, data: indio_dev);
1957
1958 return devm_iio_trigger_register(dev: &client->dev, trig_info: trigger);
1959}
1960
1961static int vcnl4000_probe(struct i2c_client *client)
1962{
1963 const struct i2c_device_id *id = i2c_client_get_device_id(client);
1964 struct vcnl4000_data *data;
1965 struct iio_dev *indio_dev;
1966 int ret;
1967
1968 indio_dev = devm_iio_device_alloc(parent: &client->dev, sizeof_priv: sizeof(*data));
1969 if (!indio_dev)
1970 return -ENOMEM;
1971
1972 data = iio_priv(indio_dev);
1973 i2c_set_clientdata(client, data: indio_dev);
1974 data->client = client;
1975 data->id = id->driver_data;
1976 data->chip_spec = &vcnl4000_chip_spec_cfg[data->id];
1977
1978 mutex_init(&data->vcnl4000_lock);
1979
1980 ret = data->chip_spec->init(data);
1981 if (ret < 0)
1982 return ret;
1983
1984 dev_dbg(&client->dev, "%s Ambient light/proximity sensor, Rev: %02x\n",
1985 data->chip_spec->prod, data->rev);
1986
1987 if (device_property_read_u32(dev: &client->dev, propname: "proximity-near-level",
1988 val: &data->near_level))
1989 data->near_level = 0;
1990
1991 indio_dev->info = data->chip_spec->info;
1992 indio_dev->channels = data->chip_spec->channels;
1993 indio_dev->num_channels = data->chip_spec->num_channels;
1994 indio_dev->name = VCNL4000_DRV_NAME;
1995 indio_dev->modes = INDIO_DIRECT_MODE;
1996
1997 if (data->chip_spec->trig_buffer_func &&
1998 data->chip_spec->buffer_setup_ops) {
1999 ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev,
2000 NULL,
2001 data->chip_spec->trig_buffer_func,
2002 data->chip_spec->buffer_setup_ops);
2003 if (ret < 0) {
2004 dev_err(&client->dev,
2005 "unable to setup iio triggered buffer\n");
2006 return ret;
2007 }
2008 }
2009
2010 if (client->irq && data->chip_spec->irq_thread) {
2011 ret = devm_request_threaded_irq(dev: &client->dev, irq: client->irq,
2012 NULL, thread_fn: data->chip_spec->irq_thread,
2013 IRQF_TRIGGER_FALLING |
2014 IRQF_ONESHOT,
2015 devname: "vcnl4000_irq",
2016 dev_id: indio_dev);
2017 if (ret < 0) {
2018 dev_err(&client->dev, "irq request failed\n");
2019 return ret;
2020 }
2021
2022 ret = vcnl4010_probe_trigger(indio_dev);
2023 if (ret < 0)
2024 return ret;
2025 }
2026
2027 ret = pm_runtime_set_active(dev: &client->dev);
2028 if (ret < 0)
2029 goto fail_poweroff;
2030
2031 ret = iio_device_register(indio_dev);
2032 if (ret < 0)
2033 goto fail_poweroff;
2034
2035 pm_runtime_enable(dev: &client->dev);
2036 pm_runtime_set_autosuspend_delay(dev: &client->dev, VCNL4000_SLEEP_DELAY_MS);
2037 pm_runtime_use_autosuspend(dev: &client->dev);
2038
2039 return 0;
2040fail_poweroff:
2041 data->chip_spec->set_power_state(data, false);
2042 return ret;
2043}
2044
2045static const struct of_device_id vcnl_4000_of_match[] = {
2046 {
2047 .compatible = "vishay,vcnl4000",
2048 .data = (void *)VCNL4000,
2049 },
2050 {
2051 .compatible = "vishay,vcnl4010",
2052 .data = (void *)VCNL4010,
2053 },
2054 {
2055 .compatible = "vishay,vcnl4020",
2056 .data = (void *)VCNL4010,
2057 },
2058 {
2059 .compatible = "vishay,vcnl4040",
2060 .data = (void *)VCNL4040,
2061 },
2062 {
2063 .compatible = "vishay,vcnl4200",
2064 .data = (void *)VCNL4200,
2065 },
2066 {},
2067};
2068MODULE_DEVICE_TABLE(of, vcnl_4000_of_match);
2069
2070static void vcnl4000_remove(struct i2c_client *client)
2071{
2072 struct iio_dev *indio_dev = i2c_get_clientdata(client);
2073 struct vcnl4000_data *data = iio_priv(indio_dev);
2074 int ret;
2075
2076 pm_runtime_dont_use_autosuspend(dev: &client->dev);
2077 pm_runtime_disable(dev: &client->dev);
2078 iio_device_unregister(indio_dev);
2079 pm_runtime_set_suspended(dev: &client->dev);
2080
2081 ret = data->chip_spec->set_power_state(data, false);
2082 if (ret)
2083 dev_warn(&client->dev, "Failed to power down (%pe)\n",
2084 ERR_PTR(ret));
2085}
2086
2087static int vcnl4000_runtime_suspend(struct device *dev)
2088{
2089 struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
2090 struct vcnl4000_data *data = iio_priv(indio_dev);
2091
2092 return data->chip_spec->set_power_state(data, false);
2093}
2094
2095static int vcnl4000_runtime_resume(struct device *dev)
2096{
2097 struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
2098 struct vcnl4000_data *data = iio_priv(indio_dev);
2099
2100 return data->chip_spec->set_power_state(data, true);
2101}
2102
2103static DEFINE_RUNTIME_DEV_PM_OPS(vcnl4000_pm_ops, vcnl4000_runtime_suspend,
2104 vcnl4000_runtime_resume, NULL);
2105
2106static struct i2c_driver vcnl4000_driver = {
2107 .driver = {
2108 .name = VCNL4000_DRV_NAME,
2109 .pm = pm_ptr(&vcnl4000_pm_ops),
2110 .of_match_table = vcnl_4000_of_match,
2111 },
2112 .probe = vcnl4000_probe,
2113 .id_table = vcnl4000_id,
2114 .remove = vcnl4000_remove,
2115};
2116
2117module_i2c_driver(vcnl4000_driver);
2118
2119MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
2120MODULE_AUTHOR("Mathieu Othacehe <m.othacehe@gmail.com>");
2121MODULE_DESCRIPTION("Vishay VCNL4000 proximity/ambient light sensor driver");
2122MODULE_LICENSE("GPL");
2123

source code of linux/drivers/iio/light/vcnl4000.c