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