^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * isl29125.c - Support for Intersil ISL29125 RGB light sensor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2014 Peter Meerwald <pmeerw@pmeerw.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * RGB light sensor with 16-bit channels for red, green, blue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * 7-bit I2C slave address 0x44
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * TODO: interrupt support, IR compensation, thresholds, 12bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^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/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/pm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/iio/iio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/iio/sysfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/iio/trigger_consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/iio/buffer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/iio/triggered_buffer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define ISL29125_DRV_NAME "isl29125"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define ISL29125_DEVICE_ID 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define ISL29125_CONF1 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define ISL29125_CONF2 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define ISL29125_CONF3 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define ISL29125_STATUS 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define ISL29125_GREEN_DATA 0x09
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define ISL29125_RED_DATA 0x0b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define ISL29125_BLUE_DATA 0x0d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define ISL29125_ID 0x7d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define ISL29125_MODE_MASK GENMASK(2, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define ISL29125_MODE_PD 0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define ISL29125_MODE_G 0x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define ISL29125_MODE_R 0x2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define ISL29125_MODE_B 0x3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define ISL29125_MODE_RGB 0x5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define ISL29125_SENSING_RANGE_0 5722 /* 375 lux full range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define ISL29125_SENSING_RANGE_1 152590 /* 10k lux full range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define ISL29125_MODE_RANGE BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define ISL29125_STATUS_CONV BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) struct isl29125_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) struct i2c_client *client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) u8 conf1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) /* Ensure timestamp is naturally aligned */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) u16 chans[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) s64 timestamp __aligned(8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) } scan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define ISL29125_CHANNEL(_color, _si) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) .type = IIO_INTENSITY, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) .modified = 1, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) .channel2 = IIO_MOD_LIGHT_##_color, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) .scan_index = _si, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) .scan_type = { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) .sign = 'u', \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) .realbits = 16, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) .storagebits = 16, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) .endianness = IIO_CPU, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) }, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) static const struct iio_chan_spec isl29125_channels[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) ISL29125_CHANNEL(GREEN, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) ISL29125_CHANNEL(RED, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) ISL29125_CHANNEL(BLUE, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) IIO_CHAN_SOFT_TIMESTAMP(3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) static const struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) u8 mode, data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) } isl29125_regs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) {ISL29125_MODE_G, ISL29125_GREEN_DATA},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) {ISL29125_MODE_R, ISL29125_RED_DATA},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) {ISL29125_MODE_B, ISL29125_BLUE_DATA},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) static int isl29125_read_data(struct isl29125_data *data, int si)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) int tries = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) ret = i2c_smbus_write_byte_data(data->client, ISL29125_CONF1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) data->conf1 | isl29125_regs[si].mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) msleep(101);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) while (tries--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) ret = i2c_smbus_read_byte_data(data->client, ISL29125_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) if (ret & ISL29125_STATUS_CONV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) msleep(20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) if (tries < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) dev_err(&data->client->dev, "data not ready\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) ret = i2c_smbus_read_word_data(data->client, isl29125_regs[si].data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) i2c_smbus_write_byte_data(data->client, ISL29125_CONF1, data->conf1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return ret;
^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) static int isl29125_read_raw(struct iio_dev *indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) struct iio_chan_spec const *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) int *val, int *val2, long mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) struct isl29125_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) switch (mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) case IIO_CHAN_INFO_RAW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) ret = iio_device_claim_direct_mode(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) ret = isl29125_read_data(data, chan->scan_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) iio_device_release_direct_mode(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) *val = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) return IIO_VAL_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) case IIO_CHAN_INFO_SCALE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) *val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) if (data->conf1 & ISL29125_MODE_RANGE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) *val2 = ISL29125_SENSING_RANGE_1; /*10k lux full range*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) *val2 = ISL29125_SENSING_RANGE_0; /*375 lux full range*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) return IIO_VAL_INT_PLUS_MICRO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) static int isl29125_write_raw(struct iio_dev *indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) struct iio_chan_spec const *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) int val, int val2, long mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) struct isl29125_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) switch (mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) case IIO_CHAN_INFO_SCALE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) if (val != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) if (val2 == ISL29125_SENSING_RANGE_1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) data->conf1 |= ISL29125_MODE_RANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) else if (val2 == ISL29125_SENSING_RANGE_0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) data->conf1 &= ~ISL29125_MODE_RANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) return i2c_smbus_write_byte_data(data->client, ISL29125_CONF1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) data->conf1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) static irqreturn_t isl29125_trigger_handler(int irq, void *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) struct iio_poll_func *pf = p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) struct iio_dev *indio_dev = pf->indio_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) struct isl29125_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) int i, j = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) for_each_set_bit(i, indio_dev->active_scan_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) indio_dev->masklength) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) int ret = i2c_smbus_read_word_data(data->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) isl29125_regs[i].data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) data->scan.chans[j++] = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) iio_get_time_ns(indio_dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) iio_trigger_notify_done(indio_dev->trig);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) static IIO_CONST_ATTR(scale_available, "0.005722 0.152590");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) static struct attribute *isl29125_attributes[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) &iio_const_attr_scale_available.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) static const struct attribute_group isl29125_attribute_group = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) .attrs = isl29125_attributes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) static const struct iio_info isl29125_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) .read_raw = isl29125_read_raw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) .write_raw = isl29125_write_raw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) .attrs = &isl29125_attribute_group,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) static int isl29125_buffer_postenable(struct iio_dev *indio_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) struct isl29125_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) data->conf1 |= ISL29125_MODE_RGB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) return i2c_smbus_write_byte_data(data->client, ISL29125_CONF1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) data->conf1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) static int isl29125_buffer_predisable(struct iio_dev *indio_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) struct isl29125_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) data->conf1 &= ~ISL29125_MODE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) data->conf1 |= ISL29125_MODE_PD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) return i2c_smbus_write_byte_data(data->client, ISL29125_CONF1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) data->conf1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) static const struct iio_buffer_setup_ops isl29125_buffer_setup_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) .postenable = isl29125_buffer_postenable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) .predisable = isl29125_buffer_predisable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) static int isl29125_probe(struct i2c_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) const struct i2c_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) struct isl29125_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) struct iio_dev *indio_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) if (indio_dev == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) i2c_set_clientdata(client, indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) data->client = client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) indio_dev->info = &isl29125_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) indio_dev->name = ISL29125_DRV_NAME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) indio_dev->channels = isl29125_channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) indio_dev->num_channels = ARRAY_SIZE(isl29125_channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) indio_dev->modes = INDIO_DIRECT_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) ret = i2c_smbus_read_byte_data(data->client, ISL29125_DEVICE_ID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) if (ret != ISL29125_ID)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) data->conf1 = ISL29125_MODE_PD | ISL29125_MODE_RANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) ret = i2c_smbus_write_byte_data(data->client, ISL29125_CONF1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) data->conf1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) ret = i2c_smbus_write_byte_data(data->client, ISL29125_STATUS, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) ret = iio_triggered_buffer_setup(indio_dev, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) isl29125_trigger_handler, &isl29125_buffer_setup_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) ret = iio_device_register(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) goto buffer_cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) buffer_cleanup:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) iio_triggered_buffer_cleanup(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) static int isl29125_powerdown(struct isl29125_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) return i2c_smbus_write_byte_data(data->client, ISL29125_CONF1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) (data->conf1 & ~ISL29125_MODE_MASK) | ISL29125_MODE_PD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) static int isl29125_remove(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) struct iio_dev *indio_dev = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) iio_device_unregister(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) iio_triggered_buffer_cleanup(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) isl29125_powerdown(iio_priv(indio_dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) #ifdef CONFIG_PM_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) static int isl29125_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) struct isl29125_data *data = iio_priv(i2c_get_clientdata(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) to_i2c_client(dev)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) return isl29125_powerdown(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) static int isl29125_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) struct isl29125_data *data = iio_priv(i2c_get_clientdata(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) to_i2c_client(dev)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) return i2c_smbus_write_byte_data(data->client, ISL29125_CONF1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) data->conf1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) static SIMPLE_DEV_PM_OPS(isl29125_pm_ops, isl29125_suspend, isl29125_resume);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) static const struct i2c_device_id isl29125_id[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) { "isl29125", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) MODULE_DEVICE_TABLE(i2c, isl29125_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) static struct i2c_driver isl29125_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) .name = ISL29125_DRV_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) .pm = &isl29125_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) .probe = isl29125_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) .remove = isl29125_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) .id_table = isl29125_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) module_i2c_driver(isl29125_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) MODULE_DESCRIPTION("ISL29125 RGB light sensor driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) MODULE_LICENSE("GPL");