1 // SPDX-License-Identifier: GPL-2.0+
3 * Azoteq IQS621/622 Ambient Light Sensors
5 * Copyright (C) 2019 Jeff LaBundy <jeff@labundy.com>
8 #include <linux/device.h>
9 #include <linux/iio/events.h>
10 #include <linux/iio/iio.h>
11 #include <linux/kernel.h>
12 #include <linux/mfd/iqs62x.h>
13 #include <linux/module.h>
14 #include <linux/mutex.h>
15 #include <linux/notifier.h>
16 #include <linux/platform_device.h>
17 #include <linux/regmap.h>
19 #define IQS621_ALS_FLAGS_LIGHT BIT(7)
20 #define IQS621_ALS_FLAGS_RANGE GENMASK(3, 0)
22 #define IQS621_ALS_UI_OUT 0x17
24 #define IQS621_ALS_THRESH_DARK 0x80
25 #define IQS621_ALS_THRESH_LIGHT 0x81
27 #define IQS622_IR_RANGE 0x15
28 #define IQS622_IR_FLAGS 0x16
29 #define IQS622_IR_FLAGS_TOUCH BIT(1)
30 #define IQS622_IR_FLAGS_PROX BIT(0)
32 #define IQS622_IR_UI_OUT 0x17
34 #define IQS622_IR_THRESH_PROX 0x91
35 #define IQS622_IR_THRESH_TOUCH 0x92
37 struct iqs621_als_private
{
38 struct iqs62x_core
*iqs62x
;
39 struct notifier_block notifier
;
52 static int iqs621_als_init(struct iqs621_als_private
*iqs621_als
)
54 struct iqs62x_core
*iqs62x
= iqs621_als
->iqs62x
;
55 unsigned int event_mask
= 0;
58 switch (iqs621_als
->ir_flags_mask
) {
59 case IQS622_IR_FLAGS_TOUCH
:
60 ret
= regmap_write(iqs62x
->regmap
, IQS622_IR_THRESH_TOUCH
,
61 iqs621_als
->thresh_prox
);
64 case IQS622_IR_FLAGS_PROX
:
65 ret
= regmap_write(iqs62x
->regmap
, IQS622_IR_THRESH_PROX
,
66 iqs621_als
->thresh_prox
);
70 ret
= regmap_write(iqs62x
->regmap
, IQS621_ALS_THRESH_LIGHT
,
71 iqs621_als
->thresh_light
);
75 ret
= regmap_write(iqs62x
->regmap
, IQS621_ALS_THRESH_DARK
,
76 iqs621_als
->thresh_dark
);
82 if (iqs621_als
->light_en
|| iqs621_als
->range_en
)
83 event_mask
|= iqs62x
->dev_desc
->als_mask
;
85 if (iqs621_als
->prox_en
)
86 event_mask
|= iqs62x
->dev_desc
->ir_mask
;
88 return regmap_update_bits(iqs62x
->regmap
, IQS620_GLBL_EVENT_MASK
,
92 static int iqs621_als_notifier(struct notifier_block
*notifier
,
93 unsigned long event_flags
, void *context
)
95 struct iqs62x_event_data
*event_data
= context
;
96 struct iqs621_als_private
*iqs621_als
;
97 struct iio_dev
*indio_dev
;
98 bool light_new
, light_old
;
99 bool prox_new
, prox_old
;
100 u8 range_new
, range_old
;
104 iqs621_als
= container_of(notifier
, struct iqs621_als_private
,
106 indio_dev
= iio_priv_to_dev(iqs621_als
);
107 timestamp
= iio_get_time_ns(indio_dev
);
109 mutex_lock(&iqs621_als
->lock
);
111 if (event_flags
& BIT(IQS62X_EVENT_SYS_RESET
)) {
112 ret
= iqs621_als_init(iqs621_als
);
114 dev_err(indio_dev
->dev
.parent
,
115 "Failed to re-initialize device: %d\n", ret
);
124 if (!iqs621_als
->light_en
&& !iqs621_als
->range_en
&&
125 !iqs621_als
->prox_en
) {
131 light_new
= event_data
->als_flags
& IQS621_ALS_FLAGS_LIGHT
;
132 light_old
= iqs621_als
->als_flags
& IQS621_ALS_FLAGS_LIGHT
;
134 if (iqs621_als
->light_en
&& light_new
&& !light_old
)
135 iio_push_event(indio_dev
,
136 IIO_UNMOD_EVENT_CODE(IIO_LIGHT
, 0,
140 else if (iqs621_als
->light_en
&& !light_new
&& light_old
)
141 iio_push_event(indio_dev
,
142 IIO_UNMOD_EVENT_CODE(IIO_LIGHT
, 0,
147 /* IQS621 and IQS622 */
148 range_new
= event_data
->als_flags
& IQS621_ALS_FLAGS_RANGE
;
149 range_old
= iqs621_als
->als_flags
& IQS621_ALS_FLAGS_RANGE
;
151 if (iqs621_als
->range_en
&& (range_new
> range_old
))
152 iio_push_event(indio_dev
,
153 IIO_UNMOD_EVENT_CODE(IIO_INTENSITY
, 0,
157 else if (iqs621_als
->range_en
&& (range_new
< range_old
))
158 iio_push_event(indio_dev
,
159 IIO_UNMOD_EVENT_CODE(IIO_INTENSITY
, 0,
165 prox_new
= event_data
->ir_flags
& iqs621_als
->ir_flags_mask
;
166 prox_old
= iqs621_als
->ir_flags
& iqs621_als
->ir_flags_mask
;
168 if (iqs621_als
->prox_en
&& prox_new
&& !prox_old
)
169 iio_push_event(indio_dev
,
170 IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY
, 0,
174 else if (iqs621_als
->prox_en
&& !prox_new
&& prox_old
)
175 iio_push_event(indio_dev
,
176 IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY
, 0,
181 iqs621_als
->als_flags
= event_data
->als_flags
;
182 iqs621_als
->ir_flags
= event_data
->ir_flags
;
186 mutex_unlock(&iqs621_als
->lock
);
191 static void iqs621_als_notifier_unregister(void *context
)
193 struct iqs621_als_private
*iqs621_als
= context
;
194 struct iio_dev
*indio_dev
= iio_priv_to_dev(iqs621_als
);
197 ret
= blocking_notifier_chain_unregister(&iqs621_als
->iqs62x
->nh
,
198 &iqs621_als
->notifier
);
200 dev_err(indio_dev
->dev
.parent
,
201 "Failed to unregister notifier: %d\n", ret
);
204 static int iqs621_als_read_raw(struct iio_dev
*indio_dev
,
205 struct iio_chan_spec
const *chan
,
206 int *val
, int *val2
, long mask
)
208 struct iqs621_als_private
*iqs621_als
= iio_priv(indio_dev
);
209 struct iqs62x_core
*iqs62x
= iqs621_als
->iqs62x
;
213 switch (chan
->type
) {
215 ret
= regmap_read(iqs62x
->regmap
, chan
->address
, val
);
219 *val
&= IQS621_ALS_FLAGS_RANGE
;
224 ret
= regmap_raw_read(iqs62x
->regmap
, chan
->address
, &val_buf
,
229 *val
= le16_to_cpu(val_buf
);
237 static int iqs621_als_read_event_config(struct iio_dev
*indio_dev
,
238 const struct iio_chan_spec
*chan
,
239 enum iio_event_type type
,
240 enum iio_event_direction dir
)
242 struct iqs621_als_private
*iqs621_als
= iio_priv(indio_dev
);
245 mutex_lock(&iqs621_als
->lock
);
247 switch (chan
->type
) {
249 ret
= iqs621_als
->light_en
;
253 ret
= iqs621_als
->range_en
;
257 ret
= iqs621_als
->prox_en
;
264 mutex_unlock(&iqs621_als
->lock
);
269 static int iqs621_als_write_event_config(struct iio_dev
*indio_dev
,
270 const struct iio_chan_spec
*chan
,
271 enum iio_event_type type
,
272 enum iio_event_direction dir
,
275 struct iqs621_als_private
*iqs621_als
= iio_priv(indio_dev
);
276 struct iqs62x_core
*iqs62x
= iqs621_als
->iqs62x
;
280 mutex_lock(&iqs621_als
->lock
);
282 ret
= regmap_read(iqs62x
->regmap
, iqs62x
->dev_desc
->als_flags
, &val
);
285 iqs621_als
->als_flags
= val
;
287 switch (chan
->type
) {
289 ret
= regmap_update_bits(iqs62x
->regmap
, IQS620_GLBL_EVENT_MASK
,
290 iqs62x
->dev_desc
->als_mask
,
291 iqs621_als
->range_en
|| state
? 0 :
294 iqs621_als
->light_en
= state
;
298 ret
= regmap_update_bits(iqs62x
->regmap
, IQS620_GLBL_EVENT_MASK
,
299 iqs62x
->dev_desc
->als_mask
,
300 iqs621_als
->light_en
|| state
? 0 :
303 iqs621_als
->range_en
= state
;
307 ret
= regmap_read(iqs62x
->regmap
, IQS622_IR_FLAGS
, &val
);
310 iqs621_als
->ir_flags
= val
;
312 ret
= regmap_update_bits(iqs62x
->regmap
, IQS620_GLBL_EVENT_MASK
,
313 iqs62x
->dev_desc
->ir_mask
,
316 iqs621_als
->prox_en
= state
;
324 mutex_unlock(&iqs621_als
->lock
);
329 static int iqs621_als_read_event_value(struct iio_dev
*indio_dev
,
330 const struct iio_chan_spec
*chan
,
331 enum iio_event_type type
,
332 enum iio_event_direction dir
,
333 enum iio_event_info info
,
336 struct iqs621_als_private
*iqs621_als
= iio_priv(indio_dev
);
337 int ret
= IIO_VAL_INT
;
339 mutex_lock(&iqs621_als
->lock
);
342 case IIO_EV_DIR_RISING
:
343 *val
= iqs621_als
->thresh_light
* 16;
346 case IIO_EV_DIR_FALLING
:
347 *val
= iqs621_als
->thresh_dark
* 4;
350 case IIO_EV_DIR_EITHER
:
351 if (iqs621_als
->ir_flags_mask
== IQS622_IR_FLAGS_TOUCH
)
352 *val
= iqs621_als
->thresh_prox
* 4;
354 *val
= iqs621_als
->thresh_prox
;
361 mutex_unlock(&iqs621_als
->lock
);
366 static int iqs621_als_write_event_value(struct iio_dev
*indio_dev
,
367 const struct iio_chan_spec
*chan
,
368 enum iio_event_type type
,
369 enum iio_event_direction dir
,
370 enum iio_event_info info
,
373 struct iqs621_als_private
*iqs621_als
= iio_priv(indio_dev
);
374 struct iqs62x_core
*iqs62x
= iqs621_als
->iqs62x
;
375 unsigned int thresh_reg
, thresh_val
;
376 u8 ir_flags_mask
, *thresh_cache
;
379 mutex_lock(&iqs621_als
->lock
);
382 case IIO_EV_DIR_RISING
:
383 thresh_reg
= IQS621_ALS_THRESH_LIGHT
;
384 thresh_val
= val
/ 16;
386 thresh_cache
= &iqs621_als
->thresh_light
;
390 case IIO_EV_DIR_FALLING
:
391 thresh_reg
= IQS621_ALS_THRESH_DARK
;
392 thresh_val
= val
/ 4;
394 thresh_cache
= &iqs621_als
->thresh_dark
;
398 case IIO_EV_DIR_EITHER
:
400 * The IQS622 supports two detection thresholds, both measured
401 * in the same arbitrary units reported by read_raw: proximity
402 * (0 through 255 in steps of 1), and touch (0 through 1020 in
405 * Based on the single detection threshold chosen by the user,
406 * select the hardware threshold that gives the best trade-off
407 * between range and resolution.
409 * By default, the close-range (but coarse) touch threshold is
410 * chosen during probe.
414 thresh_reg
= IQS622_IR_THRESH_PROX
;
417 ir_flags_mask
= IQS622_IR_FLAGS_PROX
;
421 thresh_reg
= IQS622_IR_THRESH_TOUCH
;
422 thresh_val
= val
/ 4;
424 ir_flags_mask
= IQS622_IR_FLAGS_TOUCH
;
431 thresh_cache
= &iqs621_als
->thresh_prox
;
438 if (thresh_val
> 0xFF)
441 ret
= regmap_write(iqs62x
->regmap
, thresh_reg
, thresh_val
);
445 *thresh_cache
= thresh_val
;
446 iqs621_als
->ir_flags_mask
= ir_flags_mask
;
449 mutex_unlock(&iqs621_als
->lock
);
454 static const struct iio_info iqs621_als_info
= {
455 .read_raw
= &iqs621_als_read_raw
,
456 .read_event_config
= iqs621_als_read_event_config
,
457 .write_event_config
= iqs621_als_write_event_config
,
458 .read_event_value
= iqs621_als_read_event_value
,
459 .write_event_value
= iqs621_als_write_event_value
,
462 static const struct iio_event_spec iqs621_als_range_events
[] = {
464 .type
= IIO_EV_TYPE_CHANGE
,
465 .dir
= IIO_EV_DIR_EITHER
,
466 .mask_separate
= BIT(IIO_EV_INFO_ENABLE
),
470 static const struct iio_event_spec iqs621_als_light_events
[] = {
472 .type
= IIO_EV_TYPE_THRESH
,
473 .dir
= IIO_EV_DIR_EITHER
,
474 .mask_separate
= BIT(IIO_EV_INFO_ENABLE
),
477 .type
= IIO_EV_TYPE_THRESH
,
478 .dir
= IIO_EV_DIR_RISING
,
479 .mask_separate
= BIT(IIO_EV_INFO_VALUE
),
482 .type
= IIO_EV_TYPE_THRESH
,
483 .dir
= IIO_EV_DIR_FALLING
,
484 .mask_separate
= BIT(IIO_EV_INFO_VALUE
),
488 static const struct iio_chan_spec iqs621_als_channels
[] = {
490 .type
= IIO_INTENSITY
,
491 .address
= IQS621_ALS_FLAGS
,
492 .info_mask_separate
= BIT(IIO_CHAN_INFO_RAW
),
493 .event_spec
= iqs621_als_range_events
,
494 .num_event_specs
= ARRAY_SIZE(iqs621_als_range_events
),
498 .address
= IQS621_ALS_UI_OUT
,
499 .info_mask_separate
= BIT(IIO_CHAN_INFO_PROCESSED
),
500 .event_spec
= iqs621_als_light_events
,
501 .num_event_specs
= ARRAY_SIZE(iqs621_als_light_events
),
505 static const struct iio_event_spec iqs622_als_prox_events
[] = {
507 .type
= IIO_EV_TYPE_THRESH
,
508 .dir
= IIO_EV_DIR_EITHER
,
509 .mask_separate
= BIT(IIO_EV_INFO_ENABLE
) |
510 BIT(IIO_EV_INFO_VALUE
),
514 static const struct iio_chan_spec iqs622_als_channels
[] = {
516 .type
= IIO_INTENSITY
,
517 .channel2
= IIO_MOD_LIGHT_BOTH
,
518 .address
= IQS622_ALS_FLAGS
,
519 .info_mask_separate
= BIT(IIO_CHAN_INFO_RAW
),
520 .event_spec
= iqs621_als_range_events
,
521 .num_event_specs
= ARRAY_SIZE(iqs621_als_range_events
),
525 .type
= IIO_INTENSITY
,
526 .channel2
= IIO_MOD_LIGHT_IR
,
527 .address
= IQS622_IR_RANGE
,
528 .info_mask_separate
= BIT(IIO_CHAN_INFO_RAW
),
532 .type
= IIO_PROXIMITY
,
533 .address
= IQS622_IR_UI_OUT
,
534 .info_mask_separate
= BIT(IIO_CHAN_INFO_RAW
),
535 .event_spec
= iqs622_als_prox_events
,
536 .num_event_specs
= ARRAY_SIZE(iqs622_als_prox_events
),
540 static int iqs621_als_probe(struct platform_device
*pdev
)
542 struct iqs62x_core
*iqs62x
= dev_get_drvdata(pdev
->dev
.parent
);
543 struct iqs621_als_private
*iqs621_als
;
544 struct iio_dev
*indio_dev
;
548 indio_dev
= devm_iio_device_alloc(&pdev
->dev
, sizeof(*iqs621_als
));
552 iqs621_als
= iio_priv(indio_dev
);
553 iqs621_als
->iqs62x
= iqs62x
;
555 if (iqs62x
->dev_desc
->prod_num
== IQS622_PROD_NUM
) {
556 ret
= regmap_read(iqs62x
->regmap
, IQS622_IR_THRESH_TOUCH
,
560 iqs621_als
->thresh_prox
= val
;
561 iqs621_als
->ir_flags_mask
= IQS622_IR_FLAGS_TOUCH
;
563 indio_dev
->channels
= iqs622_als_channels
;
564 indio_dev
->num_channels
= ARRAY_SIZE(iqs622_als_channels
);
566 ret
= regmap_read(iqs62x
->regmap
, IQS621_ALS_THRESH_LIGHT
,
570 iqs621_als
->thresh_light
= val
;
572 ret
= regmap_read(iqs62x
->regmap
, IQS621_ALS_THRESH_DARK
,
576 iqs621_als
->thresh_dark
= val
;
578 indio_dev
->channels
= iqs621_als_channels
;
579 indio_dev
->num_channels
= ARRAY_SIZE(iqs621_als_channels
);
582 indio_dev
->modes
= INDIO_DIRECT_MODE
;
583 indio_dev
->dev
.parent
= &pdev
->dev
;
584 indio_dev
->name
= iqs62x
->dev_desc
->dev_name
;
585 indio_dev
->info
= &iqs621_als_info
;
587 mutex_init(&iqs621_als
->lock
);
589 iqs621_als
->notifier
.notifier_call
= iqs621_als_notifier
;
590 ret
= blocking_notifier_chain_register(&iqs621_als
->iqs62x
->nh
,
591 &iqs621_als
->notifier
);
593 dev_err(&pdev
->dev
, "Failed to register notifier: %d\n", ret
);
597 ret
= devm_add_action_or_reset(&pdev
->dev
,
598 iqs621_als_notifier_unregister
,
603 return devm_iio_device_register(&pdev
->dev
, indio_dev
);
606 static struct platform_driver iqs621_als_platform_driver
= {
608 .name
= "iqs621-als",
610 .probe
= iqs621_als_probe
,
612 module_platform_driver(iqs621_als_platform_driver
);
614 MODULE_AUTHOR("Jeff LaBundy <jeff@labundy.com>");
615 MODULE_DESCRIPTION("Azoteq IQS621/622 Ambient Light Sensors");
616 MODULE_LICENSE("GPL");
617 MODULE_ALIAS("platform:iqs621-als");