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 iio_dev
*indio_dev
;
40 struct notifier_block notifier
;
53 static int iqs621_als_init(struct iqs621_als_private
*iqs621_als
)
55 struct iqs62x_core
*iqs62x
= iqs621_als
->iqs62x
;
56 unsigned int event_mask
= 0;
59 switch (iqs621_als
->ir_flags_mask
) {
60 case IQS622_IR_FLAGS_TOUCH
:
61 ret
= regmap_write(iqs62x
->regmap
, IQS622_IR_THRESH_TOUCH
,
62 iqs621_als
->thresh_prox
);
65 case IQS622_IR_FLAGS_PROX
:
66 ret
= regmap_write(iqs62x
->regmap
, IQS622_IR_THRESH_PROX
,
67 iqs621_als
->thresh_prox
);
71 ret
= regmap_write(iqs62x
->regmap
, IQS621_ALS_THRESH_LIGHT
,
72 iqs621_als
->thresh_light
);
76 ret
= regmap_write(iqs62x
->regmap
, IQS621_ALS_THRESH_DARK
,
77 iqs621_als
->thresh_dark
);
83 if (iqs621_als
->light_en
|| iqs621_als
->range_en
)
84 event_mask
|= iqs62x
->dev_desc
->als_mask
;
86 if (iqs621_als
->prox_en
)
87 event_mask
|= iqs62x
->dev_desc
->ir_mask
;
89 return regmap_update_bits(iqs62x
->regmap
, IQS620_GLBL_EVENT_MASK
,
93 static int iqs621_als_notifier(struct notifier_block
*notifier
,
94 unsigned long event_flags
, void *context
)
96 struct iqs62x_event_data
*event_data
= context
;
97 struct iqs621_als_private
*iqs621_als
;
98 struct iio_dev
*indio_dev
;
99 bool light_new
, light_old
;
100 bool prox_new
, prox_old
;
101 u8 range_new
, range_old
;
105 iqs621_als
= container_of(notifier
, struct iqs621_als_private
,
107 indio_dev
= iqs621_als
->indio_dev
;
108 timestamp
= iio_get_time_ns(indio_dev
);
110 mutex_lock(&iqs621_als
->lock
);
112 if (event_flags
& BIT(IQS62X_EVENT_SYS_RESET
)) {
113 ret
= iqs621_als_init(iqs621_als
);
115 dev_err(indio_dev
->dev
.parent
,
116 "Failed to re-initialize device: %d\n", ret
);
125 if (!iqs621_als
->light_en
&& !iqs621_als
->range_en
&&
126 !iqs621_als
->prox_en
) {
132 light_new
= event_data
->als_flags
& IQS621_ALS_FLAGS_LIGHT
;
133 light_old
= iqs621_als
->als_flags
& IQS621_ALS_FLAGS_LIGHT
;
135 if (iqs621_als
->light_en
&& light_new
&& !light_old
)
136 iio_push_event(indio_dev
,
137 IIO_UNMOD_EVENT_CODE(IIO_LIGHT
, 0,
141 else if (iqs621_als
->light_en
&& !light_new
&& light_old
)
142 iio_push_event(indio_dev
,
143 IIO_UNMOD_EVENT_CODE(IIO_LIGHT
, 0,
148 /* IQS621 and IQS622 */
149 range_new
= event_data
->als_flags
& IQS621_ALS_FLAGS_RANGE
;
150 range_old
= iqs621_als
->als_flags
& IQS621_ALS_FLAGS_RANGE
;
152 if (iqs621_als
->range_en
&& (range_new
> range_old
))
153 iio_push_event(indio_dev
,
154 IIO_UNMOD_EVENT_CODE(IIO_INTENSITY
, 0,
158 else if (iqs621_als
->range_en
&& (range_new
< range_old
))
159 iio_push_event(indio_dev
,
160 IIO_UNMOD_EVENT_CODE(IIO_INTENSITY
, 0,
166 prox_new
= event_data
->ir_flags
& iqs621_als
->ir_flags_mask
;
167 prox_old
= iqs621_als
->ir_flags
& iqs621_als
->ir_flags_mask
;
169 if (iqs621_als
->prox_en
&& prox_new
&& !prox_old
)
170 iio_push_event(indio_dev
,
171 IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY
, 0,
175 else if (iqs621_als
->prox_en
&& !prox_new
&& prox_old
)
176 iio_push_event(indio_dev
,
177 IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY
, 0,
182 iqs621_als
->als_flags
= event_data
->als_flags
;
183 iqs621_als
->ir_flags
= event_data
->ir_flags
;
187 mutex_unlock(&iqs621_als
->lock
);
192 static void iqs621_als_notifier_unregister(void *context
)
194 struct iqs621_als_private
*iqs621_als
= context
;
195 struct iio_dev
*indio_dev
= iqs621_als
->indio_dev
;
198 ret
= blocking_notifier_chain_unregister(&iqs621_als
->iqs62x
->nh
,
199 &iqs621_als
->notifier
);
201 dev_err(indio_dev
->dev
.parent
,
202 "Failed to unregister notifier: %d\n", ret
);
205 static int iqs621_als_read_raw(struct iio_dev
*indio_dev
,
206 struct iio_chan_spec
const *chan
,
207 int *val
, int *val2
, long mask
)
209 struct iqs621_als_private
*iqs621_als
= iio_priv(indio_dev
);
210 struct iqs62x_core
*iqs62x
= iqs621_als
->iqs62x
;
214 switch (chan
->type
) {
216 ret
= regmap_read(iqs62x
->regmap
, chan
->address
, val
);
220 *val
&= IQS621_ALS_FLAGS_RANGE
;
225 ret
= regmap_raw_read(iqs62x
->regmap
, chan
->address
, &val_buf
,
230 *val
= le16_to_cpu(val_buf
);
238 static int iqs621_als_read_event_config(struct iio_dev
*indio_dev
,
239 const struct iio_chan_spec
*chan
,
240 enum iio_event_type type
,
241 enum iio_event_direction dir
)
243 struct iqs621_als_private
*iqs621_als
= iio_priv(indio_dev
);
246 mutex_lock(&iqs621_als
->lock
);
248 switch (chan
->type
) {
250 ret
= iqs621_als
->light_en
;
254 ret
= iqs621_als
->range_en
;
258 ret
= iqs621_als
->prox_en
;
265 mutex_unlock(&iqs621_als
->lock
);
270 static int iqs621_als_write_event_config(struct iio_dev
*indio_dev
,
271 const struct iio_chan_spec
*chan
,
272 enum iio_event_type type
,
273 enum iio_event_direction dir
,
276 struct iqs621_als_private
*iqs621_als
= iio_priv(indio_dev
);
277 struct iqs62x_core
*iqs62x
= iqs621_als
->iqs62x
;
281 mutex_lock(&iqs621_als
->lock
);
283 ret
= regmap_read(iqs62x
->regmap
, iqs62x
->dev_desc
->als_flags
, &val
);
286 iqs621_als
->als_flags
= val
;
288 switch (chan
->type
) {
290 ret
= regmap_update_bits(iqs62x
->regmap
, IQS620_GLBL_EVENT_MASK
,
291 iqs62x
->dev_desc
->als_mask
,
292 iqs621_als
->range_en
|| state
? 0 :
295 iqs621_als
->light_en
= state
;
299 ret
= regmap_update_bits(iqs62x
->regmap
, IQS620_GLBL_EVENT_MASK
,
300 iqs62x
->dev_desc
->als_mask
,
301 iqs621_als
->light_en
|| state
? 0 :
304 iqs621_als
->range_en
= state
;
308 ret
= regmap_read(iqs62x
->regmap
, IQS622_IR_FLAGS
, &val
);
311 iqs621_als
->ir_flags
= val
;
313 ret
= regmap_update_bits(iqs62x
->regmap
, IQS620_GLBL_EVENT_MASK
,
314 iqs62x
->dev_desc
->ir_mask
,
317 iqs621_als
->prox_en
= state
;
325 mutex_unlock(&iqs621_als
->lock
);
330 static int iqs621_als_read_event_value(struct iio_dev
*indio_dev
,
331 const struct iio_chan_spec
*chan
,
332 enum iio_event_type type
,
333 enum iio_event_direction dir
,
334 enum iio_event_info info
,
337 struct iqs621_als_private
*iqs621_als
= iio_priv(indio_dev
);
338 int ret
= IIO_VAL_INT
;
340 mutex_lock(&iqs621_als
->lock
);
343 case IIO_EV_DIR_RISING
:
344 *val
= iqs621_als
->thresh_light
* 16;
347 case IIO_EV_DIR_FALLING
:
348 *val
= iqs621_als
->thresh_dark
* 4;
351 case IIO_EV_DIR_EITHER
:
352 if (iqs621_als
->ir_flags_mask
== IQS622_IR_FLAGS_TOUCH
)
353 *val
= iqs621_als
->thresh_prox
* 4;
355 *val
= iqs621_als
->thresh_prox
;
362 mutex_unlock(&iqs621_als
->lock
);
367 static int iqs621_als_write_event_value(struct iio_dev
*indio_dev
,
368 const struct iio_chan_spec
*chan
,
369 enum iio_event_type type
,
370 enum iio_event_direction dir
,
371 enum iio_event_info info
,
374 struct iqs621_als_private
*iqs621_als
= iio_priv(indio_dev
);
375 struct iqs62x_core
*iqs62x
= iqs621_als
->iqs62x
;
376 unsigned int thresh_reg
, thresh_val
;
377 u8 ir_flags_mask
, *thresh_cache
;
380 mutex_lock(&iqs621_als
->lock
);
383 case IIO_EV_DIR_RISING
:
384 thresh_reg
= IQS621_ALS_THRESH_LIGHT
;
385 thresh_val
= val
/ 16;
387 thresh_cache
= &iqs621_als
->thresh_light
;
391 case IIO_EV_DIR_FALLING
:
392 thresh_reg
= IQS621_ALS_THRESH_DARK
;
393 thresh_val
= val
/ 4;
395 thresh_cache
= &iqs621_als
->thresh_dark
;
399 case IIO_EV_DIR_EITHER
:
401 * The IQS622 supports two detection thresholds, both measured
402 * in the same arbitrary units reported by read_raw: proximity
403 * (0 through 255 in steps of 1), and touch (0 through 1020 in
406 * Based on the single detection threshold chosen by the user,
407 * select the hardware threshold that gives the best trade-off
408 * between range and resolution.
410 * By default, the close-range (but coarse) touch threshold is
411 * chosen during probe.
415 thresh_reg
= IQS622_IR_THRESH_PROX
;
418 ir_flags_mask
= IQS622_IR_FLAGS_PROX
;
422 thresh_reg
= IQS622_IR_THRESH_TOUCH
;
423 thresh_val
= val
/ 4;
425 ir_flags_mask
= IQS622_IR_FLAGS_TOUCH
;
432 thresh_cache
= &iqs621_als
->thresh_prox
;
439 if (thresh_val
> 0xFF)
442 ret
= regmap_write(iqs62x
->regmap
, thresh_reg
, thresh_val
);
446 *thresh_cache
= thresh_val
;
447 iqs621_als
->ir_flags_mask
= ir_flags_mask
;
450 mutex_unlock(&iqs621_als
->lock
);
455 static const struct iio_info iqs621_als_info
= {
456 .read_raw
= &iqs621_als_read_raw
,
457 .read_event_config
= iqs621_als_read_event_config
,
458 .write_event_config
= iqs621_als_write_event_config
,
459 .read_event_value
= iqs621_als_read_event_value
,
460 .write_event_value
= iqs621_als_write_event_value
,
463 static const struct iio_event_spec iqs621_als_range_events
[] = {
465 .type
= IIO_EV_TYPE_CHANGE
,
466 .dir
= IIO_EV_DIR_EITHER
,
467 .mask_separate
= BIT(IIO_EV_INFO_ENABLE
),
471 static const struct iio_event_spec iqs621_als_light_events
[] = {
473 .type
= IIO_EV_TYPE_THRESH
,
474 .dir
= IIO_EV_DIR_EITHER
,
475 .mask_separate
= BIT(IIO_EV_INFO_ENABLE
),
478 .type
= IIO_EV_TYPE_THRESH
,
479 .dir
= IIO_EV_DIR_RISING
,
480 .mask_separate
= BIT(IIO_EV_INFO_VALUE
),
483 .type
= IIO_EV_TYPE_THRESH
,
484 .dir
= IIO_EV_DIR_FALLING
,
485 .mask_separate
= BIT(IIO_EV_INFO_VALUE
),
489 static const struct iio_chan_spec iqs621_als_channels
[] = {
491 .type
= IIO_INTENSITY
,
492 .address
= IQS621_ALS_FLAGS
,
493 .info_mask_separate
= BIT(IIO_CHAN_INFO_RAW
),
494 .event_spec
= iqs621_als_range_events
,
495 .num_event_specs
= ARRAY_SIZE(iqs621_als_range_events
),
499 .address
= IQS621_ALS_UI_OUT
,
500 .info_mask_separate
= BIT(IIO_CHAN_INFO_PROCESSED
),
501 .event_spec
= iqs621_als_light_events
,
502 .num_event_specs
= ARRAY_SIZE(iqs621_als_light_events
),
506 static const struct iio_event_spec iqs622_als_prox_events
[] = {
508 .type
= IIO_EV_TYPE_THRESH
,
509 .dir
= IIO_EV_DIR_EITHER
,
510 .mask_separate
= BIT(IIO_EV_INFO_ENABLE
) |
511 BIT(IIO_EV_INFO_VALUE
),
515 static const struct iio_chan_spec iqs622_als_channels
[] = {
517 .type
= IIO_INTENSITY
,
518 .channel2
= IIO_MOD_LIGHT_BOTH
,
519 .address
= IQS622_ALS_FLAGS
,
520 .info_mask_separate
= BIT(IIO_CHAN_INFO_RAW
),
521 .event_spec
= iqs621_als_range_events
,
522 .num_event_specs
= ARRAY_SIZE(iqs621_als_range_events
),
526 .type
= IIO_INTENSITY
,
527 .channel2
= IIO_MOD_LIGHT_IR
,
528 .address
= IQS622_IR_RANGE
,
529 .info_mask_separate
= BIT(IIO_CHAN_INFO_RAW
),
533 .type
= IIO_PROXIMITY
,
534 .address
= IQS622_IR_UI_OUT
,
535 .info_mask_separate
= BIT(IIO_CHAN_INFO_RAW
),
536 .event_spec
= iqs622_als_prox_events
,
537 .num_event_specs
= ARRAY_SIZE(iqs622_als_prox_events
),
541 static int iqs621_als_probe(struct platform_device
*pdev
)
543 struct iqs62x_core
*iqs62x
= dev_get_drvdata(pdev
->dev
.parent
);
544 struct iqs621_als_private
*iqs621_als
;
545 struct iio_dev
*indio_dev
;
549 indio_dev
= devm_iio_device_alloc(&pdev
->dev
, sizeof(*iqs621_als
));
553 iqs621_als
= iio_priv(indio_dev
);
554 iqs621_als
->iqs62x
= iqs62x
;
555 iqs621_als
->indio_dev
= indio_dev
;
557 if (iqs62x
->dev_desc
->prod_num
== IQS622_PROD_NUM
) {
558 ret
= regmap_read(iqs62x
->regmap
, IQS622_IR_THRESH_TOUCH
,
562 iqs621_als
->thresh_prox
= val
;
563 iqs621_als
->ir_flags_mask
= IQS622_IR_FLAGS_TOUCH
;
565 indio_dev
->channels
= iqs622_als_channels
;
566 indio_dev
->num_channels
= ARRAY_SIZE(iqs622_als_channels
);
568 ret
= regmap_read(iqs62x
->regmap
, IQS621_ALS_THRESH_LIGHT
,
572 iqs621_als
->thresh_light
= val
;
574 ret
= regmap_read(iqs62x
->regmap
, IQS621_ALS_THRESH_DARK
,
578 iqs621_als
->thresh_dark
= val
;
580 indio_dev
->channels
= iqs621_als_channels
;
581 indio_dev
->num_channels
= ARRAY_SIZE(iqs621_als_channels
);
584 indio_dev
->modes
= INDIO_DIRECT_MODE
;
585 indio_dev
->name
= iqs62x
->dev_desc
->dev_name
;
586 indio_dev
->info
= &iqs621_als_info
;
588 mutex_init(&iqs621_als
->lock
);
590 iqs621_als
->notifier
.notifier_call
= iqs621_als_notifier
;
591 ret
= blocking_notifier_chain_register(&iqs621_als
->iqs62x
->nh
,
592 &iqs621_als
->notifier
);
594 dev_err(&pdev
->dev
, "Failed to register notifier: %d\n", ret
);
598 ret
= devm_add_action_or_reset(&pdev
->dev
,
599 iqs621_als_notifier_unregister
,
604 return devm_iio_device_register(&pdev
->dev
, indio_dev
);
607 static struct platform_driver iqs621_als_platform_driver
= {
609 .name
= "iqs621-als",
611 .probe
= iqs621_als_probe
,
613 module_platform_driver(iqs621_als_platform_driver
);
615 MODULE_AUTHOR("Jeff LaBundy <jeff@labundy.com>");
616 MODULE_DESCRIPTION("Azoteq IQS621/622 Ambient Light Sensors");
617 MODULE_LICENSE("GPL");
618 MODULE_ALIAS("platform:iqs621-als");