linux/drivers/iio/light/tcs3472.c
<<
>>
Prefs
   1/*
   2 * tcs3472.c - Support for TAOS TCS3472 color light-to-digital converter
   3 *
   4 * Copyright (c) 2013 Peter Meerwald <pmeerw@pmeerw.net>
   5 *
   6 * This file is subject to the terms and conditions of version 2 of
   7 * the GNU General Public License.  See the file COPYING in the main
   8 * directory of this archive for more details.
   9 *
  10 * Color light sensor with 16-bit channels for red, green, blue, clear);
  11 * 7-bit I2C slave address 0x39 (TCS34721, TCS34723) or 0x29 (TCS34725,
  12 * TCS34727)
  13 *
  14 * TODO: interrupt support, thresholds, wait time
  15 */
  16
  17#include <linux/module.h>
  18#include <linux/i2c.h>
  19#include <linux/delay.h>
  20#include <linux/pm.h>
  21
  22#include <linux/iio/iio.h>
  23#include <linux/iio/sysfs.h>
  24#include <linux/iio/trigger_consumer.h>
  25#include <linux/iio/buffer.h>
  26#include <linux/iio/triggered_buffer.h>
  27
  28#define TCS3472_DRV_NAME "tcs3472"
  29
  30#define TCS3472_COMMAND BIT(7)
  31#define TCS3472_AUTO_INCR BIT(5)
  32
  33#define TCS3472_ENABLE (TCS3472_COMMAND | 0x00)
  34#define TCS3472_ATIME (TCS3472_COMMAND | 0x01)
  35#define TCS3472_WTIME (TCS3472_COMMAND | 0x03)
  36#define TCS3472_AILT (TCS3472_COMMAND | 0x04)
  37#define TCS3472_AIHT (TCS3472_COMMAND | 0x06)
  38#define TCS3472_PERS (TCS3472_COMMAND | 0x0c)
  39#define TCS3472_CONFIG (TCS3472_COMMAND | 0x0d)
  40#define TCS3472_CONTROL (TCS3472_COMMAND | 0x0f)
  41#define TCS3472_ID (TCS3472_COMMAND | 0x12)
  42#define TCS3472_STATUS (TCS3472_COMMAND | 0x13)
  43#define TCS3472_CDATA (TCS3472_COMMAND | TCS3472_AUTO_INCR | 0x14)
  44#define TCS3472_RDATA (TCS3472_COMMAND | TCS3472_AUTO_INCR | 0x16)
  45#define TCS3472_GDATA (TCS3472_COMMAND | TCS3472_AUTO_INCR | 0x18)
  46#define TCS3472_BDATA (TCS3472_COMMAND | TCS3472_AUTO_INCR | 0x1a)
  47
  48#define TCS3472_STATUS_AVALID BIT(0)
  49#define TCS3472_ENABLE_AEN BIT(1)
  50#define TCS3472_ENABLE_PON BIT(0)
  51#define TCS3472_CONTROL_AGAIN_MASK (BIT(0) | BIT(1))
  52
  53struct tcs3472_data {
  54        struct i2c_client *client;
  55        struct mutex lock;
  56        u8 enable;
  57        u8 control;
  58        u8 atime;
  59        u16 buffer[8]; /* 4 16-bit channels + 64-bit timestamp */
  60};
  61
  62#define TCS3472_CHANNEL(_color, _si, _addr) { \
  63        .type = IIO_INTENSITY, \
  64        .modified = 1, \
  65        .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
  66        .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_CALIBSCALE) | \
  67                BIT(IIO_CHAN_INFO_INT_TIME), \
  68        .channel2 = IIO_MOD_LIGHT_##_color, \
  69        .address = _addr, \
  70        .scan_index = _si, \
  71        .scan_type = { \
  72                .sign = 'u', \
  73                .realbits = 16, \
  74                .storagebits = 16, \
  75                .endianness = IIO_CPU, \
  76        }, \
  77}
  78
  79static const int tcs3472_agains[] = { 1, 4, 16, 60 };
  80
  81static const struct iio_chan_spec tcs3472_channels[] = {
  82        TCS3472_CHANNEL(CLEAR, 0, TCS3472_CDATA),
  83        TCS3472_CHANNEL(RED, 1, TCS3472_RDATA),
  84        TCS3472_CHANNEL(GREEN, 2, TCS3472_GDATA),
  85        TCS3472_CHANNEL(BLUE, 3, TCS3472_BDATA),
  86        IIO_CHAN_SOFT_TIMESTAMP(4),
  87};
  88
  89static int tcs3472_req_data(struct tcs3472_data *data)
  90{
  91        int tries = 50;
  92        int ret;
  93
  94        while (tries--) {
  95                ret = i2c_smbus_read_byte_data(data->client, TCS3472_STATUS);
  96                if (ret < 0)
  97                        return ret;
  98                if (ret & TCS3472_STATUS_AVALID)
  99                        break;
 100                msleep(20);
 101        }
 102
 103        if (tries < 0) {
 104                dev_err(&data->client->dev, "data not ready\n");
 105                return -EIO;
 106        }
 107
 108        return 0;
 109}
 110
 111static int tcs3472_read_raw(struct iio_dev *indio_dev,
 112                           struct iio_chan_spec const *chan,
 113                           int *val, int *val2, long mask)
 114{
 115        struct tcs3472_data *data = iio_priv(indio_dev);
 116        int ret;
 117
 118        switch (mask) {
 119        case IIO_CHAN_INFO_RAW:
 120                if (iio_buffer_enabled(indio_dev))
 121                        return -EBUSY;
 122
 123                mutex_lock(&data->lock);
 124                ret = tcs3472_req_data(data);
 125                if (ret < 0) {
 126                        mutex_unlock(&data->lock);
 127                        return ret;
 128                }
 129                ret = i2c_smbus_read_word_data(data->client, chan->address);
 130                mutex_unlock(&data->lock);
 131                if (ret < 0)
 132                        return ret;
 133                *val = ret;
 134                return IIO_VAL_INT;
 135        case IIO_CHAN_INFO_CALIBSCALE:
 136                *val = tcs3472_agains[data->control &
 137                        TCS3472_CONTROL_AGAIN_MASK];
 138                return IIO_VAL_INT;
 139        case IIO_CHAN_INFO_INT_TIME:
 140                *val = 0;
 141                *val2 = (256 - data->atime) * 2400;
 142                return IIO_VAL_INT_PLUS_MICRO;
 143        }
 144        return -EINVAL;
 145}
 146
 147static int tcs3472_write_raw(struct iio_dev *indio_dev,
 148                               struct iio_chan_spec const *chan,
 149                               int val, int val2, long mask)
 150{
 151        struct tcs3472_data *data = iio_priv(indio_dev);
 152        int i;
 153
 154        switch (mask) {
 155        case IIO_CHAN_INFO_CALIBSCALE:
 156                if (val2 != 0)
 157                        return -EINVAL;
 158                for (i = 0; i < ARRAY_SIZE(tcs3472_agains); i++) {
 159                        if (val == tcs3472_agains[i]) {
 160                                data->control &= ~TCS3472_CONTROL_AGAIN_MASK;
 161                                data->control |= i;
 162                                return i2c_smbus_write_byte_data(
 163                                        data->client, TCS3472_CONTROL,
 164                                        data->control);
 165                        }
 166                }
 167                return -EINVAL;
 168        case IIO_CHAN_INFO_INT_TIME:
 169                if (val != 0)
 170                        return -EINVAL;
 171                for (i = 0; i < 256; i++) {
 172                        if (val2 == (256 - i) * 2400) {
 173                                data->atime = i;
 174                                return i2c_smbus_write_word_data(
 175                                        data->client, TCS3472_ATIME,
 176                                        data->atime);
 177                        }
 178
 179                }
 180                return -EINVAL;
 181        }
 182        return -EINVAL;
 183}
 184
 185static irqreturn_t tcs3472_trigger_handler(int irq, void *p)
 186{
 187        struct iio_poll_func *pf = p;
 188        struct iio_dev *indio_dev = pf->indio_dev;
 189        struct tcs3472_data *data = iio_priv(indio_dev);
 190        int i, j = 0;
 191
 192        int ret = tcs3472_req_data(data);
 193        if (ret < 0)
 194                goto done;
 195
 196        for_each_set_bit(i, indio_dev->active_scan_mask,
 197                indio_dev->masklength) {
 198                ret = i2c_smbus_read_word_data(data->client,
 199                        TCS3472_CDATA + 2*i);
 200                if (ret < 0)
 201                        goto done;
 202
 203                data->buffer[j++] = ret;
 204        }
 205
 206        iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
 207                iio_get_time_ns());
 208
 209done:
 210        iio_trigger_notify_done(indio_dev->trig);
 211
 212        return IRQ_HANDLED;
 213}
 214
 215static ssize_t tcs3472_show_int_time_available(struct device *dev,
 216                                        struct device_attribute *attr,
 217                                        char *buf)
 218{
 219        size_t len = 0;
 220        int i;
 221
 222        for (i = 1; i <= 256; i++)
 223                len += scnprintf(buf + len, PAGE_SIZE - len, "0.%06d ",
 224                        2400 * i);
 225
 226        /* replace trailing space by newline */
 227        buf[len - 1] = '\n';
 228
 229        return len;
 230}
 231
 232static IIO_CONST_ATTR(calibscale_available, "1 4 16 60");
 233static IIO_DEV_ATTR_INT_TIME_AVAIL(tcs3472_show_int_time_available);
 234
 235static struct attribute *tcs3472_attributes[] = {
 236        &iio_const_attr_calibscale_available.dev_attr.attr,
 237        &iio_dev_attr_integration_time_available.dev_attr.attr,
 238        NULL
 239};
 240
 241static const struct attribute_group tcs3472_attribute_group = {
 242        .attrs = tcs3472_attributes,
 243};
 244
 245static const struct iio_info tcs3472_info = {
 246        .read_raw = tcs3472_read_raw,
 247        .write_raw = tcs3472_write_raw,
 248        .attrs = &tcs3472_attribute_group,
 249        .driver_module = THIS_MODULE,
 250};
 251
 252static int tcs3472_probe(struct i2c_client *client,
 253                           const struct i2c_device_id *id)
 254{
 255        struct tcs3472_data *data;
 256        struct iio_dev *indio_dev;
 257        int ret;
 258
 259        indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
 260        if (indio_dev == NULL)
 261                return -ENOMEM;
 262
 263        data = iio_priv(indio_dev);
 264        i2c_set_clientdata(client, indio_dev);
 265        data->client = client;
 266        mutex_init(&data->lock);
 267
 268        indio_dev->dev.parent = &client->dev;
 269        indio_dev->info = &tcs3472_info;
 270        indio_dev->name = TCS3472_DRV_NAME;
 271        indio_dev->channels = tcs3472_channels;
 272        indio_dev->num_channels = ARRAY_SIZE(tcs3472_channels);
 273        indio_dev->modes = INDIO_DIRECT_MODE;
 274
 275        ret = i2c_smbus_read_byte_data(data->client, TCS3472_ID);
 276        if (ret < 0)
 277                return ret;
 278
 279        if (ret == 0x44)
 280                dev_info(&client->dev, "TCS34721/34725 found\n");
 281        else if (ret == 0x4d)
 282                dev_info(&client->dev, "TCS34723/34727 found\n");
 283        else
 284                return -ENODEV;
 285
 286        ret = i2c_smbus_read_byte_data(data->client, TCS3472_CONTROL);
 287        if (ret < 0)
 288                return ret;
 289        data->control = ret;
 290
 291        ret = i2c_smbus_read_byte_data(data->client, TCS3472_ATIME);
 292        if (ret < 0)
 293                return ret;
 294        data->atime = ret;
 295
 296        ret = i2c_smbus_read_byte_data(data->client, TCS3472_ENABLE);
 297        if (ret < 0)
 298                return ret;
 299
 300        /* enable device */
 301        data->enable = ret | TCS3472_ENABLE_PON | TCS3472_ENABLE_AEN;
 302        ret = i2c_smbus_write_byte_data(data->client, TCS3472_ENABLE,
 303                data->enable);
 304        if (ret < 0)
 305                return ret;
 306
 307        ret = iio_triggered_buffer_setup(indio_dev, NULL,
 308                tcs3472_trigger_handler, NULL);
 309        if (ret < 0)
 310                return ret;
 311
 312        ret = iio_device_register(indio_dev);
 313        if (ret < 0)
 314                goto buffer_cleanup;
 315
 316        return 0;
 317
 318buffer_cleanup:
 319        iio_triggered_buffer_cleanup(indio_dev);
 320        return ret;
 321}
 322
 323static int tcs3472_powerdown(struct tcs3472_data *data)
 324{
 325        return i2c_smbus_write_byte_data(data->client, TCS3472_ENABLE,
 326                data->enable & ~(TCS3472_ENABLE_AEN | TCS3472_ENABLE_PON));
 327}
 328
 329static int tcs3472_remove(struct i2c_client *client)
 330{
 331        struct iio_dev *indio_dev = i2c_get_clientdata(client);
 332
 333        iio_device_unregister(indio_dev);
 334        iio_triggered_buffer_cleanup(indio_dev);
 335        tcs3472_powerdown(iio_priv(indio_dev));
 336
 337        return 0;
 338}
 339
 340#ifdef CONFIG_PM_SLEEP
 341static int tcs3472_suspend(struct device *dev)
 342{
 343        struct tcs3472_data *data = iio_priv(i2c_get_clientdata(
 344                to_i2c_client(dev)));
 345        return tcs3472_powerdown(data);
 346}
 347
 348static int tcs3472_resume(struct device *dev)
 349{
 350        struct tcs3472_data *data = iio_priv(i2c_get_clientdata(
 351                to_i2c_client(dev)));
 352        return i2c_smbus_write_byte_data(data->client, TCS3472_ENABLE,
 353                data->enable | (TCS3472_ENABLE_AEN | TCS3472_ENABLE_PON));
 354}
 355#endif
 356
 357static SIMPLE_DEV_PM_OPS(tcs3472_pm_ops, tcs3472_suspend, tcs3472_resume);
 358
 359static const struct i2c_device_id tcs3472_id[] = {
 360        { "tcs3472", 0 },
 361        { }
 362};
 363MODULE_DEVICE_TABLE(i2c, tcs3472_id);
 364
 365static struct i2c_driver tcs3472_driver = {
 366        .driver = {
 367                .name   = TCS3472_DRV_NAME,
 368                .pm     = &tcs3472_pm_ops,
 369        },
 370        .probe          = tcs3472_probe,
 371        .remove         = tcs3472_remove,
 372        .id_table       = tcs3472_id,
 373};
 374module_i2c_driver(tcs3472_driver);
 375
 376MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
 377MODULE_DESCRIPTION("TCS3472 color light sensors driver");
 378MODULE_LICENSE("GPL");
 379