1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Azoteq IQS621/622 Ambient Light Sensors 4 * 5 * Copyright (C) 2019 Jeff LaBundy <jeff@labundy.com> 6 */ 7 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> 18 19 #define IQS621_ALS_FLAGS_LIGHT BIT(7) 20 #define IQS621_ALS_FLAGS_RANGE GENMASK(3, 0) 21 22 #define IQS621_ALS_UI_OUT 0x17 23 24 #define IQS621_ALS_THRESH_DARK 0x80 25 #define IQS621_ALS_THRESH_LIGHT 0x81 26 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) 31 32 #define IQS622_IR_UI_OUT 0x17 33 34 #define IQS622_IR_THRESH_PROX 0x91 35 #define IQS622_IR_THRESH_TOUCH 0x92 36 37 struct iqs621_als_private { 38 struct iqs62x_core *iqs62x; 39 struct notifier_block notifier; 40 struct mutex lock; 41 bool light_en; 42 bool range_en; 43 bool prox_en; 44 u8 als_flags; 45 u8 ir_flags_mask; 46 u8 ir_flags; 47 u8 thresh_light; 48 u8 thresh_dark; 49 u8 thresh_prox; 50 }; 51 52 static int iqs621_als_init(struct iqs621_als_private *iqs621_als) 53 { 54 struct iqs62x_core *iqs62x = iqs621_als->iqs62x; 55 unsigned int event_mask = 0; 56 int ret; 57 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); 62 break; 63 64 case IQS622_IR_FLAGS_PROX: 65 ret = regmap_write(iqs62x->regmap, IQS622_IR_THRESH_PROX, 66 iqs621_als->thresh_prox); 67 break; 68 69 default: 70 ret = regmap_write(iqs62x->regmap, IQS621_ALS_THRESH_LIGHT, 71 iqs621_als->thresh_light); 72 if (ret) 73 return ret; 74 75 ret = regmap_write(iqs62x->regmap, IQS621_ALS_THRESH_DARK, 76 iqs621_als->thresh_dark); 77 } 78 79 if (ret) 80 return ret; 81 82 if (iqs621_als->light_en || iqs621_als->range_en) 83 event_mask |= iqs62x->dev_desc->als_mask; 84 85 if (iqs621_als->prox_en) 86 event_mask |= iqs62x->dev_desc->ir_mask; 87 88 return regmap_update_bits(iqs62x->regmap, IQS620_GLBL_EVENT_MASK, 89 event_mask, 0); 90 } 91 92 static int iqs621_als_notifier(struct notifier_block *notifier, 93 unsigned long event_flags, void *context) 94 { 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; 101 s64 timestamp; 102 int ret; 103 104 iqs621_als = container_of(notifier, struct iqs621_als_private, 105 notifier); 106 indio_dev = iio_priv_to_dev(iqs621_als); 107 timestamp = iio_get_time_ns(indio_dev); 108 109 mutex_lock(&iqs621_als->lock); 110 111 if (event_flags & BIT(IQS62X_EVENT_SYS_RESET)) { 112 ret = iqs621_als_init(iqs621_als); 113 if (ret) { 114 dev_err(indio_dev->dev.parent, 115 "Failed to re-initialize device: %d\n", ret); 116 ret = NOTIFY_BAD; 117 } else { 118 ret = NOTIFY_OK; 119 } 120 121 goto err_mutex; 122 } 123 124 if (!iqs621_als->light_en && !iqs621_als->range_en && 125 !iqs621_als->prox_en) { 126 ret = NOTIFY_DONE; 127 goto err_mutex; 128 } 129 130 /* IQS621 only */ 131 light_new = event_data->als_flags & IQS621_ALS_FLAGS_LIGHT; 132 light_old = iqs621_als->als_flags & IQS621_ALS_FLAGS_LIGHT; 133 134 if (iqs621_als->light_en && light_new && !light_old) 135 iio_push_event(indio_dev, 136 IIO_UNMOD_EVENT_CODE(IIO_LIGHT, 0, 137 IIO_EV_TYPE_THRESH, 138 IIO_EV_DIR_RISING), 139 timestamp); 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, 143 IIO_EV_TYPE_THRESH, 144 IIO_EV_DIR_FALLING), 145 timestamp); 146 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; 150 151 if (iqs621_als->range_en && (range_new > range_old)) 152 iio_push_event(indio_dev, 153 IIO_UNMOD_EVENT_CODE(IIO_INTENSITY, 0, 154 IIO_EV_TYPE_CHANGE, 155 IIO_EV_DIR_RISING), 156 timestamp); 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, 160 IIO_EV_TYPE_CHANGE, 161 IIO_EV_DIR_FALLING), 162 timestamp); 163 164 /* IQS622 only */ 165 prox_new = event_data->ir_flags & iqs621_als->ir_flags_mask; 166 prox_old = iqs621_als->ir_flags & iqs621_als->ir_flags_mask; 167 168 if (iqs621_als->prox_en && prox_new && !prox_old) 169 iio_push_event(indio_dev, 170 IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, 0, 171 IIO_EV_TYPE_THRESH, 172 IIO_EV_DIR_RISING), 173 timestamp); 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, 177 IIO_EV_TYPE_THRESH, 178 IIO_EV_DIR_FALLING), 179 timestamp); 180 181 iqs621_als->als_flags = event_data->als_flags; 182 iqs621_als->ir_flags = event_data->ir_flags; 183 ret = NOTIFY_OK; 184 185 err_mutex: 186 mutex_unlock(&iqs621_als->lock); 187 188 return ret; 189 } 190 191 static void iqs621_als_notifier_unregister(void *context) 192 { 193 struct iqs621_als_private *iqs621_als = context; 194 struct iio_dev *indio_dev = iio_priv_to_dev(iqs621_als); 195 int ret; 196 197 ret = blocking_notifier_chain_unregister(&iqs621_als->iqs62x->nh, 198 &iqs621_als->notifier); 199 if (ret) 200 dev_err(indio_dev->dev.parent, 201 "Failed to unregister notifier: %d\n", ret); 202 } 203 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) 207 { 208 struct iqs621_als_private *iqs621_als = iio_priv(indio_dev); 209 struct iqs62x_core *iqs62x = iqs621_als->iqs62x; 210 int ret; 211 __le16 val_buf; 212 213 switch (chan->type) { 214 case IIO_INTENSITY: 215 ret = regmap_read(iqs62x->regmap, chan->address, val); 216 if (ret) 217 return ret; 218 219 *val &= IQS621_ALS_FLAGS_RANGE; 220 return IIO_VAL_INT; 221 222 case IIO_PROXIMITY: 223 case IIO_LIGHT: 224 ret = regmap_raw_read(iqs62x->regmap, chan->address, &val_buf, 225 sizeof(val_buf)); 226 if (ret) 227 return ret; 228 229 *val = le16_to_cpu(val_buf); 230 return IIO_VAL_INT; 231 232 default: 233 return -EINVAL; 234 } 235 } 236 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) 241 { 242 struct iqs621_als_private *iqs621_als = iio_priv(indio_dev); 243 int ret; 244 245 mutex_lock(&iqs621_als->lock); 246 247 switch (chan->type) { 248 case IIO_LIGHT: 249 ret = iqs621_als->light_en; 250 break; 251 252 case IIO_INTENSITY: 253 ret = iqs621_als->range_en; 254 break; 255 256 case IIO_PROXIMITY: 257 ret = iqs621_als->prox_en; 258 break; 259 260 default: 261 ret = -EINVAL; 262 } 263 264 mutex_unlock(&iqs621_als->lock); 265 266 return ret; 267 } 268 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, 273 int state) 274 { 275 struct iqs621_als_private *iqs621_als = iio_priv(indio_dev); 276 struct iqs62x_core *iqs62x = iqs621_als->iqs62x; 277 unsigned int val; 278 int ret; 279 280 mutex_lock(&iqs621_als->lock); 281 282 ret = regmap_read(iqs62x->regmap, iqs62x->dev_desc->als_flags, &val); 283 if (ret) 284 goto err_mutex; 285 iqs621_als->als_flags = val; 286 287 switch (chan->type) { 288 case IIO_LIGHT: 289 ret = regmap_update_bits(iqs62x->regmap, IQS620_GLBL_EVENT_MASK, 290 iqs62x->dev_desc->als_mask, 291 iqs621_als->range_en || state ? 0 : 292 0xFF); 293 if (!ret) 294 iqs621_als->light_en = state; 295 break; 296 297 case IIO_INTENSITY: 298 ret = regmap_update_bits(iqs62x->regmap, IQS620_GLBL_EVENT_MASK, 299 iqs62x->dev_desc->als_mask, 300 iqs621_als->light_en || state ? 0 : 301 0xFF); 302 if (!ret) 303 iqs621_als->range_en = state; 304 break; 305 306 case IIO_PROXIMITY: 307 ret = regmap_read(iqs62x->regmap, IQS622_IR_FLAGS, &val); 308 if (ret) 309 goto err_mutex; 310 iqs621_als->ir_flags = val; 311 312 ret = regmap_update_bits(iqs62x->regmap, IQS620_GLBL_EVENT_MASK, 313 iqs62x->dev_desc->ir_mask, 314 state ? 0 : 0xFF); 315 if (!ret) 316 iqs621_als->prox_en = state; 317 break; 318 319 default: 320 ret = -EINVAL; 321 } 322 323 err_mutex: 324 mutex_unlock(&iqs621_als->lock); 325 326 return ret; 327 } 328 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, 334 int *val, int *val2) 335 { 336 struct iqs621_als_private *iqs621_als = iio_priv(indio_dev); 337 int ret = IIO_VAL_INT; 338 339 mutex_lock(&iqs621_als->lock); 340 341 switch (dir) { 342 case IIO_EV_DIR_RISING: 343 *val = iqs621_als->thresh_light * 16; 344 break; 345 346 case IIO_EV_DIR_FALLING: 347 *val = iqs621_als->thresh_dark * 4; 348 break; 349 350 case IIO_EV_DIR_EITHER: 351 if (iqs621_als->ir_flags_mask == IQS622_IR_FLAGS_TOUCH) 352 *val = iqs621_als->thresh_prox * 4; 353 else 354 *val = iqs621_als->thresh_prox; 355 break; 356 357 default: 358 ret = -EINVAL; 359 } 360 361 mutex_unlock(&iqs621_als->lock); 362 363 return ret; 364 } 365 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, 371 int val, int val2) 372 { 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; 377 int ret = -EINVAL; 378 379 mutex_lock(&iqs621_als->lock); 380 381 switch (dir) { 382 case IIO_EV_DIR_RISING: 383 thresh_reg = IQS621_ALS_THRESH_LIGHT; 384 thresh_val = val / 16; 385 386 thresh_cache = &iqs621_als->thresh_light; 387 ir_flags_mask = 0; 388 break; 389 390 case IIO_EV_DIR_FALLING: 391 thresh_reg = IQS621_ALS_THRESH_DARK; 392 thresh_val = val / 4; 393 394 thresh_cache = &iqs621_als->thresh_dark; 395 ir_flags_mask = 0; 396 break; 397 398 case IIO_EV_DIR_EITHER: 399 /* 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 403 * steps of 4). 404 * 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. 408 * 409 * By default, the close-range (but coarse) touch threshold is 410 * chosen during probe. 411 */ 412 switch (val) { 413 case 0 ... 255: 414 thresh_reg = IQS622_IR_THRESH_PROX; 415 thresh_val = val; 416 417 ir_flags_mask = IQS622_IR_FLAGS_PROX; 418 break; 419 420 case 256 ... 1020: 421 thresh_reg = IQS622_IR_THRESH_TOUCH; 422 thresh_val = val / 4; 423 424 ir_flags_mask = IQS622_IR_FLAGS_TOUCH; 425 break; 426 427 default: 428 goto err_mutex; 429 } 430 431 thresh_cache = &iqs621_als->thresh_prox; 432 break; 433 434 default: 435 goto err_mutex; 436 } 437 438 if (thresh_val > 0xFF) 439 goto err_mutex; 440 441 ret = regmap_write(iqs62x->regmap, thresh_reg, thresh_val); 442 if (ret) 443 goto err_mutex; 444 445 *thresh_cache = thresh_val; 446 iqs621_als->ir_flags_mask = ir_flags_mask; 447 448 err_mutex: 449 mutex_unlock(&iqs621_als->lock); 450 451 return ret; 452 } 453 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, 460 }; 461 462 static const struct iio_event_spec iqs621_als_range_events[] = { 463 { 464 .type = IIO_EV_TYPE_CHANGE, 465 .dir = IIO_EV_DIR_EITHER, 466 .mask_separate = BIT(IIO_EV_INFO_ENABLE), 467 }, 468 }; 469 470 static const struct iio_event_spec iqs621_als_light_events[] = { 471 { 472 .type = IIO_EV_TYPE_THRESH, 473 .dir = IIO_EV_DIR_EITHER, 474 .mask_separate = BIT(IIO_EV_INFO_ENABLE), 475 }, 476 { 477 .type = IIO_EV_TYPE_THRESH, 478 .dir = IIO_EV_DIR_RISING, 479 .mask_separate = BIT(IIO_EV_INFO_VALUE), 480 }, 481 { 482 .type = IIO_EV_TYPE_THRESH, 483 .dir = IIO_EV_DIR_FALLING, 484 .mask_separate = BIT(IIO_EV_INFO_VALUE), 485 }, 486 }; 487 488 static const struct iio_chan_spec iqs621_als_channels[] = { 489 { 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), 495 }, 496 { 497 .type = IIO_LIGHT, 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), 502 }, 503 }; 504 505 static const struct iio_event_spec iqs622_als_prox_events[] = { 506 { 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), 511 }, 512 }; 513 514 static const struct iio_chan_spec iqs622_als_channels[] = { 515 { 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), 522 .modified = true, 523 }, 524 { 525 .type = IIO_INTENSITY, 526 .channel2 = IIO_MOD_LIGHT_IR, 527 .address = IQS622_IR_RANGE, 528 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 529 .modified = true, 530 }, 531 { 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), 537 }, 538 }; 539 540 static int iqs621_als_probe(struct platform_device *pdev) 541 { 542 struct iqs62x_core *iqs62x = dev_get_drvdata(pdev->dev.parent); 543 struct iqs621_als_private *iqs621_als; 544 struct iio_dev *indio_dev; 545 unsigned int val; 546 int ret; 547 548 indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*iqs621_als)); 549 if (!indio_dev) 550 return -ENOMEM; 551 552 iqs621_als = iio_priv(indio_dev); 553 iqs621_als->iqs62x = iqs62x; 554 555 if (iqs62x->dev_desc->prod_num == IQS622_PROD_NUM) { 556 ret = regmap_read(iqs62x->regmap, IQS622_IR_THRESH_TOUCH, 557 &val); 558 if (ret) 559 return ret; 560 iqs621_als->thresh_prox = val; 561 iqs621_als->ir_flags_mask = IQS622_IR_FLAGS_TOUCH; 562 563 indio_dev->channels = iqs622_als_channels; 564 indio_dev->num_channels = ARRAY_SIZE(iqs622_als_channels); 565 } else { 566 ret = regmap_read(iqs62x->regmap, IQS621_ALS_THRESH_LIGHT, 567 &val); 568 if (ret) 569 return ret; 570 iqs621_als->thresh_light = val; 571 572 ret = regmap_read(iqs62x->regmap, IQS621_ALS_THRESH_DARK, 573 &val); 574 if (ret) 575 return ret; 576 iqs621_als->thresh_dark = val; 577 578 indio_dev->channels = iqs621_als_channels; 579 indio_dev->num_channels = ARRAY_SIZE(iqs621_als_channels); 580 } 581 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; 586 587 mutex_init(&iqs621_als->lock); 588 589 iqs621_als->notifier.notifier_call = iqs621_als_notifier; 590 ret = blocking_notifier_chain_register(&iqs621_als->iqs62x->nh, 591 &iqs621_als->notifier); 592 if (ret) { 593 dev_err(&pdev->dev, "Failed to register notifier: %d\n", ret); 594 return ret; 595 } 596 597 ret = devm_add_action_or_reset(&pdev->dev, 598 iqs621_als_notifier_unregister, 599 iqs621_als); 600 if (ret) 601 return ret; 602 603 return devm_iio_device_register(&pdev->dev, indio_dev); 604 } 605 606 static struct platform_driver iqs621_als_platform_driver = { 607 .driver = { 608 .name = "iqs621-als", 609 }, 610 .probe = iqs621_als_probe, 611 }; 612 module_platform_driver(iqs621_als_platform_driver); 613 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"); 618