Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * isl29125.c - Support for Intersil ISL29125 RGB light sensor
0004  *
0005  * Copyright (c) 2014 Peter Meerwald <pmeerw@pmeerw.net>
0006  *
0007  * RGB light sensor with 16-bit channels for red, green, blue);
0008  * 7-bit I2C slave address 0x44
0009  *
0010  * TODO: interrupt support, IR compensation, thresholds, 12bit
0011  */
0012 
0013 #include <linux/module.h>
0014 #include <linux/i2c.h>
0015 #include <linux/delay.h>
0016 #include <linux/pm.h>
0017 
0018 #include <linux/iio/iio.h>
0019 #include <linux/iio/sysfs.h>
0020 #include <linux/iio/trigger_consumer.h>
0021 #include <linux/iio/buffer.h>
0022 #include <linux/iio/triggered_buffer.h>
0023 
0024 #define ISL29125_DRV_NAME "isl29125"
0025 
0026 #define ISL29125_DEVICE_ID 0x00
0027 #define ISL29125_CONF1 0x01
0028 #define ISL29125_CONF2 0x02
0029 #define ISL29125_CONF3 0x03
0030 #define ISL29125_STATUS 0x08
0031 #define ISL29125_GREEN_DATA 0x09
0032 #define ISL29125_RED_DATA 0x0b
0033 #define ISL29125_BLUE_DATA 0x0d
0034 
0035 #define ISL29125_ID 0x7d
0036 
0037 #define ISL29125_MODE_MASK GENMASK(2, 0)
0038 #define ISL29125_MODE_PD 0x0
0039 #define ISL29125_MODE_G 0x1
0040 #define ISL29125_MODE_R 0x2
0041 #define ISL29125_MODE_B 0x3
0042 #define ISL29125_MODE_RGB 0x5
0043 
0044 #define ISL29125_SENSING_RANGE_0 5722   /* 375 lux full range */
0045 #define ISL29125_SENSING_RANGE_1 152590 /* 10k lux full range */
0046 
0047 #define ISL29125_MODE_RANGE BIT(3)
0048 
0049 #define ISL29125_STATUS_CONV BIT(1)
0050 
0051 struct isl29125_data {
0052     struct i2c_client *client;
0053     u8 conf1;
0054     /* Ensure timestamp is naturally aligned */
0055     struct {
0056         u16 chans[3];
0057         s64 timestamp __aligned(8);
0058     } scan;
0059 };
0060 
0061 #define ISL29125_CHANNEL(_color, _si) { \
0062     .type = IIO_INTENSITY, \
0063     .modified = 1, \
0064     .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
0065     .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
0066     .channel2 = IIO_MOD_LIGHT_##_color, \
0067     .scan_index = _si, \
0068     .scan_type = { \
0069         .sign = 'u', \
0070         .realbits = 16, \
0071         .storagebits = 16, \
0072         .endianness = IIO_CPU, \
0073     }, \
0074 }
0075 
0076 static const struct iio_chan_spec isl29125_channels[] = {
0077     ISL29125_CHANNEL(GREEN, 0),
0078     ISL29125_CHANNEL(RED, 1),
0079     ISL29125_CHANNEL(BLUE, 2),
0080     IIO_CHAN_SOFT_TIMESTAMP(3),
0081 };
0082 
0083 static const struct {
0084     u8 mode, data;
0085 } isl29125_regs[] = {
0086     {ISL29125_MODE_G, ISL29125_GREEN_DATA},
0087     {ISL29125_MODE_R, ISL29125_RED_DATA},
0088     {ISL29125_MODE_B, ISL29125_BLUE_DATA},
0089 };
0090 
0091 static int isl29125_read_data(struct isl29125_data *data, int si)
0092 {
0093     int tries = 5;
0094     int ret;
0095 
0096     ret = i2c_smbus_write_byte_data(data->client, ISL29125_CONF1,
0097         data->conf1 | isl29125_regs[si].mode);
0098     if (ret < 0)
0099         return ret;
0100 
0101     msleep(101);
0102 
0103     while (tries--) {
0104         ret = i2c_smbus_read_byte_data(data->client, ISL29125_STATUS);
0105         if (ret < 0)
0106             goto fail;
0107         if (ret & ISL29125_STATUS_CONV)
0108             break;
0109         msleep(20);
0110     }
0111 
0112     if (tries < 0) {
0113         dev_err(&data->client->dev, "data not ready\n");
0114         ret = -EIO;
0115         goto fail;
0116     }
0117 
0118     ret = i2c_smbus_read_word_data(data->client, isl29125_regs[si].data);
0119 
0120 fail:
0121     i2c_smbus_write_byte_data(data->client, ISL29125_CONF1, data->conf1);
0122     return ret;
0123 }
0124 
0125 static int isl29125_read_raw(struct iio_dev *indio_dev,
0126                struct iio_chan_spec const *chan,
0127                int *val, int *val2, long mask)
0128 {
0129     struct isl29125_data *data = iio_priv(indio_dev);
0130     int ret;
0131 
0132     switch (mask) {
0133     case IIO_CHAN_INFO_RAW:
0134         ret = iio_device_claim_direct_mode(indio_dev);
0135         if (ret)
0136             return ret;
0137         ret = isl29125_read_data(data, chan->scan_index);
0138         iio_device_release_direct_mode(indio_dev);
0139         if (ret < 0)
0140             return ret;
0141         *val = ret;
0142         return IIO_VAL_INT;
0143     case IIO_CHAN_INFO_SCALE:
0144         *val = 0;
0145         if (data->conf1 & ISL29125_MODE_RANGE)
0146             *val2 = ISL29125_SENSING_RANGE_1; /*10k lux full range*/
0147         else
0148             *val2 = ISL29125_SENSING_RANGE_0; /*375 lux full range*/
0149         return IIO_VAL_INT_PLUS_MICRO;
0150     }
0151     return -EINVAL;
0152 }
0153 
0154 static int isl29125_write_raw(struct iio_dev *indio_dev,
0155                    struct iio_chan_spec const *chan,
0156                    int val, int val2, long mask)
0157 {
0158     struct isl29125_data *data = iio_priv(indio_dev);
0159 
0160     switch (mask) {
0161     case IIO_CHAN_INFO_SCALE:
0162         if (val != 0)
0163             return -EINVAL;
0164         if (val2 == ISL29125_SENSING_RANGE_1)
0165             data->conf1 |= ISL29125_MODE_RANGE;
0166         else if (val2 == ISL29125_SENSING_RANGE_0)
0167             data->conf1 &= ~ISL29125_MODE_RANGE;
0168         else
0169             return -EINVAL;
0170         return i2c_smbus_write_byte_data(data->client, ISL29125_CONF1,
0171             data->conf1);
0172     default:
0173         return -EINVAL;
0174     }
0175 }
0176 
0177 static irqreturn_t isl29125_trigger_handler(int irq, void *p)
0178 {
0179     struct iio_poll_func *pf = p;
0180     struct iio_dev *indio_dev = pf->indio_dev;
0181     struct isl29125_data *data = iio_priv(indio_dev);
0182     int i, j = 0;
0183 
0184     for_each_set_bit(i, indio_dev->active_scan_mask,
0185         indio_dev->masklength) {
0186         int ret = i2c_smbus_read_word_data(data->client,
0187             isl29125_regs[i].data);
0188         if (ret < 0)
0189             goto done;
0190 
0191         data->scan.chans[j++] = ret;
0192     }
0193 
0194     iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
0195         iio_get_time_ns(indio_dev));
0196 
0197 done:
0198     iio_trigger_notify_done(indio_dev->trig);
0199 
0200     return IRQ_HANDLED;
0201 }
0202 
0203 static IIO_CONST_ATTR(scale_available, "0.005722 0.152590");
0204 
0205 static struct attribute *isl29125_attributes[] = {
0206     &iio_const_attr_scale_available.dev_attr.attr,
0207     NULL
0208 };
0209 
0210 static const struct attribute_group isl29125_attribute_group = {
0211     .attrs = isl29125_attributes,
0212 };
0213 
0214 static const struct iio_info isl29125_info = {
0215     .read_raw = isl29125_read_raw,
0216     .write_raw = isl29125_write_raw,
0217     .attrs = &isl29125_attribute_group,
0218 };
0219 
0220 static int isl29125_buffer_postenable(struct iio_dev *indio_dev)
0221 {
0222     struct isl29125_data *data = iio_priv(indio_dev);
0223 
0224     data->conf1 |= ISL29125_MODE_RGB;
0225     return i2c_smbus_write_byte_data(data->client, ISL29125_CONF1,
0226         data->conf1);
0227 }
0228 
0229 static int isl29125_buffer_predisable(struct iio_dev *indio_dev)
0230 {
0231     struct isl29125_data *data = iio_priv(indio_dev);
0232 
0233     data->conf1 &= ~ISL29125_MODE_MASK;
0234     data->conf1 |= ISL29125_MODE_PD;
0235     return i2c_smbus_write_byte_data(data->client, ISL29125_CONF1,
0236         data->conf1);
0237 }
0238 
0239 static const struct iio_buffer_setup_ops isl29125_buffer_setup_ops = {
0240     .postenable = isl29125_buffer_postenable,
0241     .predisable = isl29125_buffer_predisable,
0242 };
0243 
0244 static int isl29125_probe(struct i2c_client *client,
0245                const struct i2c_device_id *id)
0246 {
0247     struct isl29125_data *data;
0248     struct iio_dev *indio_dev;
0249     int ret;
0250 
0251     indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
0252     if (indio_dev == NULL)
0253         return -ENOMEM;
0254 
0255     data = iio_priv(indio_dev);
0256     i2c_set_clientdata(client, indio_dev);
0257     data->client = client;
0258 
0259     indio_dev->info = &isl29125_info;
0260     indio_dev->name = ISL29125_DRV_NAME;
0261     indio_dev->channels = isl29125_channels;
0262     indio_dev->num_channels = ARRAY_SIZE(isl29125_channels);
0263     indio_dev->modes = INDIO_DIRECT_MODE;
0264 
0265     ret = i2c_smbus_read_byte_data(data->client, ISL29125_DEVICE_ID);
0266     if (ret < 0)
0267         return ret;
0268     if (ret != ISL29125_ID)
0269         return -ENODEV;
0270 
0271     data->conf1 = ISL29125_MODE_PD | ISL29125_MODE_RANGE;
0272     ret = i2c_smbus_write_byte_data(data->client, ISL29125_CONF1,
0273         data->conf1);
0274     if (ret < 0)
0275         return ret;
0276 
0277     ret = i2c_smbus_write_byte_data(data->client, ISL29125_STATUS, 0);
0278     if (ret < 0)
0279         return ret;
0280 
0281     ret = iio_triggered_buffer_setup(indio_dev, NULL,
0282         isl29125_trigger_handler, &isl29125_buffer_setup_ops);
0283     if (ret < 0)
0284         return ret;
0285 
0286     ret = iio_device_register(indio_dev);
0287     if (ret < 0)
0288         goto buffer_cleanup;
0289 
0290     return 0;
0291 
0292 buffer_cleanup:
0293     iio_triggered_buffer_cleanup(indio_dev);
0294     return ret;
0295 }
0296 
0297 static int isl29125_powerdown(struct isl29125_data *data)
0298 {
0299     return i2c_smbus_write_byte_data(data->client, ISL29125_CONF1,
0300         (data->conf1 & ~ISL29125_MODE_MASK) | ISL29125_MODE_PD);
0301 }
0302 
0303 static int isl29125_remove(struct i2c_client *client)
0304 {
0305     struct iio_dev *indio_dev = i2c_get_clientdata(client);
0306 
0307     iio_device_unregister(indio_dev);
0308     iio_triggered_buffer_cleanup(indio_dev);
0309     isl29125_powerdown(iio_priv(indio_dev));
0310 
0311     return 0;
0312 }
0313 
0314 static int isl29125_suspend(struct device *dev)
0315 {
0316     struct isl29125_data *data = iio_priv(i2c_get_clientdata(
0317         to_i2c_client(dev)));
0318     return isl29125_powerdown(data);
0319 }
0320 
0321 static int isl29125_resume(struct device *dev)
0322 {
0323     struct isl29125_data *data = iio_priv(i2c_get_clientdata(
0324         to_i2c_client(dev)));
0325     return i2c_smbus_write_byte_data(data->client, ISL29125_CONF1,
0326         data->conf1);
0327 }
0328 
0329 static DEFINE_SIMPLE_DEV_PM_OPS(isl29125_pm_ops, isl29125_suspend,
0330                 isl29125_resume);
0331 
0332 static const struct i2c_device_id isl29125_id[] = {
0333     { "isl29125", 0 },
0334     { }
0335 };
0336 MODULE_DEVICE_TABLE(i2c, isl29125_id);
0337 
0338 static struct i2c_driver isl29125_driver = {
0339     .driver = {
0340         .name   = ISL29125_DRV_NAME,
0341         .pm = pm_sleep_ptr(&isl29125_pm_ops),
0342     },
0343     .probe      = isl29125_probe,
0344     .remove     = isl29125_remove,
0345     .id_table   = isl29125_id,
0346 };
0347 module_i2c_driver(isl29125_driver);
0348 
0349 MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
0350 MODULE_DESCRIPTION("ISL29125 RGB light sensor driver");
0351 MODULE_LICENSE("GPL");