linux/drivers/iio/light/tsl2583.c
<<
>>
Prefs
   1/*
   2 * Device driver for monitoring ambient light intensity (lux)
   3 * within the TAOS tsl258x family of devices (tsl2580, tsl2581, tsl2583).
   4 *
   5 * Copyright (c) 2011, TAOS Corporation.
   6 * Copyright (c) 2016-2017 Brian Masney <masneyb@onstation.org>
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License as published by
  10 * the Free Software Foundation; either version 2 of the License, or
  11 * (at your option) any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful, but WITHOUT
  14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  15 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  16 * more details.
  17 */
  18
  19#include <linux/kernel.h>
  20#include <linux/i2c.h>
  21#include <linux/errno.h>
  22#include <linux/delay.h>
  23#include <linux/string.h>
  24#include <linux/mutex.h>
  25#include <linux/unistd.h>
  26#include <linux/slab.h>
  27#include <linux/module.h>
  28#include <linux/iio/iio.h>
  29#include <linux/iio/sysfs.h>
  30#include <linux/pm_runtime.h>
  31
  32/* Device Registers and Masks */
  33#define TSL2583_CNTRL                   0x00
  34#define TSL2583_ALS_TIME                0X01
  35#define TSL2583_INTERRUPT               0x02
  36#define TSL2583_GAIN                    0x07
  37#define TSL2583_REVID                   0x11
  38#define TSL2583_CHIPID                  0x12
  39#define TSL2583_ALS_CHAN0LO             0x14
  40#define TSL2583_ALS_CHAN0HI             0x15
  41#define TSL2583_ALS_CHAN1LO             0x16
  42#define TSL2583_ALS_CHAN1HI             0x17
  43#define TSL2583_TMR_LO                  0x18
  44#define TSL2583_TMR_HI                  0x19
  45
  46/* tsl2583 cmd reg masks */
  47#define TSL2583_CMD_REG                 0x80
  48#define TSL2583_CMD_SPL_FN              0x60
  49#define TSL2583_CMD_ALS_INT_CLR         0x01
  50
  51/* tsl2583 cntrl reg masks */
  52#define TSL2583_CNTL_ADC_ENBL           0x02
  53#define TSL2583_CNTL_PWR_OFF            0x00
  54#define TSL2583_CNTL_PWR_ON             0x01
  55
  56/* tsl2583 status reg masks */
  57#define TSL2583_STA_ADC_VALID           0x01
  58#define TSL2583_STA_ADC_INTR            0x10
  59
  60/* Lux calculation constants */
  61#define TSL2583_LUX_CALC_OVER_FLOW      65535
  62
  63#define TSL2583_INTERRUPT_DISABLED      0x00
  64
  65#define TSL2583_CHIP_ID                 0x90
  66#define TSL2583_CHIP_ID_MASK            0xf0
  67
  68#define TSL2583_POWER_OFF_DELAY_MS      2000
  69
  70/* Per-device data */
  71struct tsl2583_als_info {
  72        u16 als_ch0;
  73        u16 als_ch1;
  74        u16 lux;
  75};
  76
  77struct tsl2583_lux {
  78        unsigned int ratio;
  79        unsigned int ch0;
  80        unsigned int ch1;
  81};
  82
  83static const struct tsl2583_lux tsl2583_default_lux[] = {
  84        {  9830,  8520, 15729 },
  85        { 12452, 10807, 23344 },
  86        { 14746,  6383, 11705 },
  87        { 17695,  4063,  6554 },
  88        {     0,     0,     0 }  /* Termination segment */
  89};
  90
  91#define TSL2583_MAX_LUX_TABLE_ENTRIES 11
  92
  93struct tsl2583_settings {
  94        int als_time;
  95        int als_gain;
  96        int als_gain_trim;
  97        int als_cal_target;
  98
  99        /*
 100         * This structure is intentionally large to accommodate updates via
 101         * sysfs. Sized to 11 = max 10 segments + 1 termination segment.
 102         * Assumption is that one and only one type of glass used.
 103         */
 104        struct tsl2583_lux als_device_lux[TSL2583_MAX_LUX_TABLE_ENTRIES];
 105};
 106
 107struct tsl2583_chip {
 108        struct mutex als_mutex;
 109        struct i2c_client *client;
 110        struct tsl2583_als_info als_cur_info;
 111        struct tsl2583_settings als_settings;
 112        int als_time_scale;
 113        int als_saturation;
 114};
 115
 116struct gainadj {
 117        s16 ch0;
 118        s16 ch1;
 119        s16 mean;
 120};
 121
 122/* Index = (0 - 3) Used to validate the gain selection index */
 123static const struct gainadj gainadj[] = {
 124        { 1, 1, 1 },
 125        { 8, 8, 8 },
 126        { 16, 16, 16 },
 127        { 107, 115, 111 }
 128};
 129
 130/*
 131 * Provides initial operational parameter defaults.
 132 * These defaults may be changed through the device's sysfs files.
 133 */
 134static void tsl2583_defaults(struct tsl2583_chip *chip)
 135{
 136        /*
 137         * The integration time must be a multiple of 50ms and within the
 138         * range [50, 600] ms.
 139         */
 140        chip->als_settings.als_time = 100;
 141
 142        /*
 143         * This is an index into the gainadj table. Assume clear glass as the
 144         * default.
 145         */
 146        chip->als_settings.als_gain = 0;
 147
 148        /* Default gain trim to account for aperture effects */
 149        chip->als_settings.als_gain_trim = 1000;
 150
 151        /* Known external ALS reading used for calibration */
 152        chip->als_settings.als_cal_target = 130;
 153
 154        /* Default lux table. */
 155        memcpy(chip->als_settings.als_device_lux, tsl2583_default_lux,
 156               sizeof(tsl2583_default_lux));
 157}
 158
 159/*
 160 * Reads and calculates current lux value.
 161 * The raw ch0 and ch1 values of the ambient light sensed in the last
 162 * integration cycle are read from the device.
 163 * Time scale factor array values are adjusted based on the integration time.
 164 * The raw values are multiplied by a scale factor, and device gain is obtained
 165 * using gain index. Limit checks are done next, then the ratio of a multiple
 166 * of ch1 value, to the ch0 value, is calculated. The array als_device_lux[]
 167 * declared above is then scanned to find the first ratio value that is just
 168 * above the ratio we just calculated. The ch0 and ch1 multiplier constants in
 169 * the array are then used along with the time scale factor array values, to
 170 * calculate the lux.
 171 */
 172static int tsl2583_get_lux(struct iio_dev *indio_dev)
 173{
 174        u16 ch0, ch1; /* separated ch0/ch1 data from device */
 175        u32 lux; /* raw lux calculated from device data */
 176        u64 lux64;
 177        u32 ratio;
 178        u8 buf[5];
 179        struct tsl2583_lux *p;
 180        struct tsl2583_chip *chip = iio_priv(indio_dev);
 181        int i, ret;
 182
 183        ret = i2c_smbus_read_byte_data(chip->client, TSL2583_CMD_REG);
 184        if (ret < 0) {
 185                dev_err(&chip->client->dev, "%s: failed to read CMD_REG register\n",
 186                        __func__);
 187                goto done;
 188        }
 189
 190        /* is data new & valid */
 191        if (!(ret & TSL2583_STA_ADC_INTR)) {
 192                dev_err(&chip->client->dev, "%s: data not valid; returning last value\n",
 193                        __func__);
 194                ret = chip->als_cur_info.lux; /* return LAST VALUE */
 195                goto done;
 196        }
 197
 198        for (i = 0; i < 4; i++) {
 199                int reg = TSL2583_CMD_REG | (TSL2583_ALS_CHAN0LO + i);
 200
 201                ret = i2c_smbus_read_byte_data(chip->client, reg);
 202                if (ret < 0) {
 203                        dev_err(&chip->client->dev, "%s: failed to read register %x\n",
 204                                __func__, reg);
 205                        goto done;
 206                }
 207                buf[i] = ret;
 208        }
 209
 210        /*
 211         * Clear the pending interrupt status bit on the chip to allow the next
 212         * integration cycle to start. This has to be done even though this
 213         * driver currently does not support interrupts.
 214         */
 215        ret = i2c_smbus_write_byte(chip->client,
 216                                   (TSL2583_CMD_REG | TSL2583_CMD_SPL_FN |
 217                                    TSL2583_CMD_ALS_INT_CLR));
 218        if (ret < 0) {
 219                dev_err(&chip->client->dev, "%s: failed to clear the interrupt bit\n",
 220                        __func__);
 221                goto done; /* have no data, so return failure */
 222        }
 223
 224        /* extract ALS/lux data */
 225        ch0 = le16_to_cpup((const __le16 *)&buf[0]);
 226        ch1 = le16_to_cpup((const __le16 *)&buf[2]);
 227
 228        chip->als_cur_info.als_ch0 = ch0;
 229        chip->als_cur_info.als_ch1 = ch1;
 230
 231        if ((ch0 >= chip->als_saturation) || (ch1 >= chip->als_saturation))
 232                goto return_max;
 233
 234        if (!ch0) {
 235                /*
 236                 * The sensor appears to be in total darkness so set the
 237                 * calculated lux to 0 and return early to avoid a division by
 238                 * zero below when calculating the ratio.
 239                 */
 240                ret = 0;
 241                chip->als_cur_info.lux = 0;
 242                goto done;
 243        }
 244
 245        /* calculate ratio */
 246        ratio = (ch1 << 15) / ch0;
 247
 248        /* convert to unscaled lux using the pointer to the table */
 249        for (p = (struct tsl2583_lux *)chip->als_settings.als_device_lux;
 250             p->ratio != 0 && p->ratio < ratio; p++)
 251                ;
 252
 253        if (p->ratio == 0) {
 254                lux = 0;
 255        } else {
 256                u32 ch0lux, ch1lux;
 257
 258                ch0lux = ((ch0 * p->ch0) +
 259                          (gainadj[chip->als_settings.als_gain].ch0 >> 1))
 260                         / gainadj[chip->als_settings.als_gain].ch0;
 261                ch1lux = ((ch1 * p->ch1) +
 262                          (gainadj[chip->als_settings.als_gain].ch1 >> 1))
 263                         / gainadj[chip->als_settings.als_gain].ch1;
 264
 265                /* note: lux is 31 bit max at this point */
 266                if (ch1lux > ch0lux) {
 267                        dev_dbg(&chip->client->dev, "%s: No Data - Returning 0\n",
 268                                __func__);
 269                        ret = 0;
 270                        chip->als_cur_info.lux = 0;
 271                        goto done;
 272                }
 273
 274                lux = ch0lux - ch1lux;
 275        }
 276
 277        /* adjust for active time scale */
 278        if (chip->als_time_scale == 0)
 279                lux = 0;
 280        else
 281                lux = (lux + (chip->als_time_scale >> 1)) /
 282                        chip->als_time_scale;
 283
 284        /*
 285         * Adjust for active gain scale.
 286         * The tsl2583_default_lux tables above have a factor of 8192 built in,
 287         * so we need to shift right.
 288         * User-specified gain provides a multiplier.
 289         * Apply user-specified gain before shifting right to retain precision.
 290         * Use 64 bits to avoid overflow on multiplication.
 291         * Then go back to 32 bits before division to avoid using div_u64().
 292         */
 293        lux64 = lux;
 294        lux64 = lux64 * chip->als_settings.als_gain_trim;
 295        lux64 >>= 13;
 296        lux = lux64;
 297        lux = (lux + 500) / 1000;
 298
 299        if (lux > TSL2583_LUX_CALC_OVER_FLOW) { /* check for overflow */
 300return_max:
 301                lux = TSL2583_LUX_CALC_OVER_FLOW;
 302        }
 303
 304        /* Update the structure with the latest VALID lux. */
 305        chip->als_cur_info.lux = lux;
 306        ret = lux;
 307
 308done:
 309        return ret;
 310}
 311
 312/*
 313 * Obtain single reading and calculate the als_gain_trim (later used
 314 * to derive actual lux).
 315 * Return updated gain_trim value.
 316 */
 317static int tsl2583_als_calibrate(struct iio_dev *indio_dev)
 318{
 319        struct tsl2583_chip *chip = iio_priv(indio_dev);
 320        unsigned int gain_trim_val;
 321        int ret;
 322        int lux_val;
 323
 324        ret = i2c_smbus_read_byte_data(chip->client,
 325                                       TSL2583_CMD_REG | TSL2583_CNTRL);
 326        if (ret < 0) {
 327                dev_err(&chip->client->dev,
 328                        "%s: failed to read from the CNTRL register\n",
 329                        __func__);
 330                return ret;
 331        }
 332
 333        if ((ret & (TSL2583_CNTL_ADC_ENBL | TSL2583_CNTL_PWR_ON))
 334                        != (TSL2583_CNTL_ADC_ENBL | TSL2583_CNTL_PWR_ON)) {
 335                dev_err(&chip->client->dev,
 336                        "%s: Device is not powered on and/or ADC is not enabled\n",
 337                        __func__);
 338                return -EINVAL;
 339        } else if ((ret & TSL2583_STA_ADC_VALID) != TSL2583_STA_ADC_VALID) {
 340                dev_err(&chip->client->dev,
 341                        "%s: The two ADC channels have not completed an integration cycle\n",
 342                        __func__);
 343                return -ENODATA;
 344        }
 345
 346        lux_val = tsl2583_get_lux(indio_dev);
 347        if (lux_val < 0) {
 348                dev_err(&chip->client->dev, "%s: failed to get lux\n",
 349                        __func__);
 350                return lux_val;
 351        }
 352
 353        gain_trim_val = (unsigned int)(((chip->als_settings.als_cal_target)
 354                        * chip->als_settings.als_gain_trim) / lux_val);
 355        if ((gain_trim_val < 250) || (gain_trim_val > 4000)) {
 356                dev_err(&chip->client->dev,
 357                        "%s: trim_val of %d is not within the range [250, 4000]\n",
 358                        __func__, gain_trim_val);
 359                return -ENODATA;
 360        }
 361
 362        chip->als_settings.als_gain_trim = (int)gain_trim_val;
 363
 364        return 0;
 365}
 366
 367static int tsl2583_set_als_time(struct tsl2583_chip *chip)
 368{
 369        int als_count, als_time, ret;
 370        u8 val;
 371
 372        /* determine als integration register */
 373        als_count = (chip->als_settings.als_time * 100 + 135) / 270;
 374        if (!als_count)
 375                als_count = 1; /* ensure at least one cycle */
 376
 377        /* convert back to time (encompasses overrides) */
 378        als_time = (als_count * 27 + 5) / 10;
 379
 380        val = 256 - als_count;
 381        ret = i2c_smbus_write_byte_data(chip->client,
 382                                        TSL2583_CMD_REG | TSL2583_ALS_TIME,
 383                                        val);
 384        if (ret < 0) {
 385                dev_err(&chip->client->dev, "%s: failed to set the als time to %d\n",
 386                        __func__, val);
 387                return ret;
 388        }
 389
 390        /* set chip struct re scaling and saturation */
 391        chip->als_saturation = als_count * 922; /* 90% of full scale */
 392        chip->als_time_scale = (als_time + 25) / 50;
 393
 394        return ret;
 395}
 396
 397static int tsl2583_set_als_gain(struct tsl2583_chip *chip)
 398{
 399        int ret;
 400
 401        /* Set the gain based on als_settings struct */
 402        ret = i2c_smbus_write_byte_data(chip->client,
 403                                        TSL2583_CMD_REG | TSL2583_GAIN,
 404                                        chip->als_settings.als_gain);
 405        if (ret < 0)
 406                dev_err(&chip->client->dev,
 407                        "%s: failed to set the gain to %d\n", __func__,
 408                        chip->als_settings.als_gain);
 409
 410        return ret;
 411}
 412
 413static int tsl2583_set_power_state(struct tsl2583_chip *chip, u8 state)
 414{
 415        int ret;
 416
 417        ret = i2c_smbus_write_byte_data(chip->client,
 418                                        TSL2583_CMD_REG | TSL2583_CNTRL, state);
 419        if (ret < 0)
 420                dev_err(&chip->client->dev,
 421                        "%s: failed to set the power state to %d\n", __func__,
 422                        state);
 423
 424        return ret;
 425}
 426
 427/*
 428 * Turn the device on.
 429 * Configuration must be set before calling this function.
 430 */
 431static int tsl2583_chip_init_and_power_on(struct iio_dev *indio_dev)
 432{
 433        struct tsl2583_chip *chip = iio_priv(indio_dev);
 434        int ret;
 435
 436        /* Power on the device; ADC off. */
 437        ret = tsl2583_set_power_state(chip, TSL2583_CNTL_PWR_ON);
 438        if (ret < 0)
 439                return ret;
 440
 441        ret = i2c_smbus_write_byte_data(chip->client,
 442                                        TSL2583_CMD_REG | TSL2583_INTERRUPT,
 443                                        TSL2583_INTERRUPT_DISABLED);
 444        if (ret < 0) {
 445                dev_err(&chip->client->dev,
 446                        "%s: failed to disable interrupts\n", __func__);
 447                return ret;
 448        }
 449
 450        ret = tsl2583_set_als_time(chip);
 451        if (ret < 0)
 452                return ret;
 453
 454        ret = tsl2583_set_als_gain(chip);
 455        if (ret < 0)
 456                return ret;
 457
 458        usleep_range(3000, 3500);
 459
 460        ret = tsl2583_set_power_state(chip, TSL2583_CNTL_PWR_ON |
 461                                            TSL2583_CNTL_ADC_ENBL);
 462        if (ret < 0)
 463                return ret;
 464
 465        return ret;
 466}
 467
 468/* Sysfs Interface Functions */
 469
 470static ssize_t in_illuminance_input_target_show(struct device *dev,
 471                                                struct device_attribute *attr,
 472                                                char *buf)
 473{
 474        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 475        struct tsl2583_chip *chip = iio_priv(indio_dev);
 476        int ret;
 477
 478        mutex_lock(&chip->als_mutex);
 479        ret = sprintf(buf, "%d\n", chip->als_settings.als_cal_target);
 480        mutex_unlock(&chip->als_mutex);
 481
 482        return ret;
 483}
 484
 485static ssize_t in_illuminance_input_target_store(struct device *dev,
 486                                                 struct device_attribute *attr,
 487                                                 const char *buf, size_t len)
 488{
 489        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 490        struct tsl2583_chip *chip = iio_priv(indio_dev);
 491        int value;
 492
 493        if (kstrtoint(buf, 0, &value) || !value)
 494                return -EINVAL;
 495
 496        mutex_lock(&chip->als_mutex);
 497        chip->als_settings.als_cal_target = value;
 498        mutex_unlock(&chip->als_mutex);
 499
 500        return len;
 501}
 502
 503static ssize_t in_illuminance_calibrate_store(struct device *dev,
 504                                              struct device_attribute *attr,
 505                                              const char *buf, size_t len)
 506{
 507        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 508        struct tsl2583_chip *chip = iio_priv(indio_dev);
 509        int value, ret;
 510
 511        if (kstrtoint(buf, 0, &value) || value != 1)
 512                return -EINVAL;
 513
 514        mutex_lock(&chip->als_mutex);
 515
 516        ret = tsl2583_als_calibrate(indio_dev);
 517        if (ret < 0)
 518                goto done;
 519
 520        ret = len;
 521done:
 522        mutex_unlock(&chip->als_mutex);
 523
 524        return ret;
 525}
 526
 527static ssize_t in_illuminance_lux_table_show(struct device *dev,
 528                                             struct device_attribute *attr,
 529                                             char *buf)
 530{
 531        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 532        struct tsl2583_chip *chip = iio_priv(indio_dev);
 533        unsigned int i;
 534        int offset = 0;
 535
 536        for (i = 0; i < ARRAY_SIZE(chip->als_settings.als_device_lux); i++) {
 537                offset += sprintf(buf + offset, "%u,%u,%u,",
 538                                  chip->als_settings.als_device_lux[i].ratio,
 539                                  chip->als_settings.als_device_lux[i].ch0,
 540                                  chip->als_settings.als_device_lux[i].ch1);
 541                if (chip->als_settings.als_device_lux[i].ratio == 0) {
 542                        /*
 543                         * We just printed the first "0" entry.
 544                         * Now get rid of the extra "," and break.
 545                         */
 546                        offset--;
 547                        break;
 548                }
 549        }
 550
 551        offset += sprintf(buf + offset, "\n");
 552
 553        return offset;
 554}
 555
 556static ssize_t in_illuminance_lux_table_store(struct device *dev,
 557                                              struct device_attribute *attr,
 558                                              const char *buf, size_t len)
 559{
 560        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 561        struct tsl2583_chip *chip = iio_priv(indio_dev);
 562        const unsigned int max_ints = TSL2583_MAX_LUX_TABLE_ENTRIES * 3;
 563        int value[TSL2583_MAX_LUX_TABLE_ENTRIES * 3 + 1];
 564        int ret = -EINVAL;
 565        unsigned int n;
 566
 567        mutex_lock(&chip->als_mutex);
 568
 569        get_options(buf, ARRAY_SIZE(value), value);
 570
 571        /*
 572         * We now have an array of ints starting at value[1], and
 573         * enumerated by value[0].
 574         * We expect each group of three ints is one table entry,
 575         * and the last table entry is all 0.
 576         */
 577        n = value[0];
 578        if ((n % 3) || n < 6 || n > max_ints) {
 579                dev_err(dev,
 580                        "%s: The number of entries in the lux table must be a multiple of 3 and within the range [6, %d]\n",
 581                        __func__, max_ints);
 582                goto done;
 583        }
 584        if ((value[n - 2] | value[n - 1] | value[n]) != 0) {
 585                dev_err(dev, "%s: The last 3 entries in the lux table must be zeros.\n",
 586                        __func__);
 587                goto done;
 588        }
 589
 590        memcpy(chip->als_settings.als_device_lux, &value[1],
 591               value[0] * sizeof(value[1]));
 592
 593        ret = len;
 594
 595done:
 596        mutex_unlock(&chip->als_mutex);
 597
 598        return ret;
 599}
 600
 601static IIO_CONST_ATTR(in_illuminance_calibscale_available, "1 8 16 111");
 602static IIO_CONST_ATTR(in_illuminance_integration_time_available,
 603                      "0.000050 0.000100 0.000150 0.000200 0.000250 0.000300 0.000350 0.000400 0.000450 0.000500 0.000550 0.000600 0.000650");
 604static IIO_DEVICE_ATTR_RW(in_illuminance_input_target, 0);
 605static IIO_DEVICE_ATTR_WO(in_illuminance_calibrate, 0);
 606static IIO_DEVICE_ATTR_RW(in_illuminance_lux_table, 0);
 607
 608static struct attribute *sysfs_attrs_ctrl[] = {
 609        &iio_const_attr_in_illuminance_calibscale_available.dev_attr.attr,
 610        &iio_const_attr_in_illuminance_integration_time_available.dev_attr.attr,
 611        &iio_dev_attr_in_illuminance_input_target.dev_attr.attr,
 612        &iio_dev_attr_in_illuminance_calibrate.dev_attr.attr,
 613        &iio_dev_attr_in_illuminance_lux_table.dev_attr.attr,
 614        NULL
 615};
 616
 617static const struct attribute_group tsl2583_attribute_group = {
 618        .attrs = sysfs_attrs_ctrl,
 619};
 620
 621static const struct iio_chan_spec tsl2583_channels[] = {
 622        {
 623                .type = IIO_LIGHT,
 624                .modified = 1,
 625                .channel2 = IIO_MOD_LIGHT_IR,
 626                .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
 627        },
 628        {
 629                .type = IIO_LIGHT,
 630                .modified = 1,
 631                .channel2 = IIO_MOD_LIGHT_BOTH,
 632                .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
 633        },
 634        {
 635                .type = IIO_LIGHT,
 636                .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
 637                                      BIT(IIO_CHAN_INFO_CALIBBIAS) |
 638                                      BIT(IIO_CHAN_INFO_CALIBSCALE) |
 639                                      BIT(IIO_CHAN_INFO_INT_TIME),
 640        },
 641};
 642
 643static int tsl2583_set_pm_runtime_busy(struct tsl2583_chip *chip, bool on)
 644{
 645        int ret;
 646
 647        if (on) {
 648                ret = pm_runtime_get_sync(&chip->client->dev);
 649                if (ret < 0)
 650                        pm_runtime_put_noidle(&chip->client->dev);
 651        } else {
 652                pm_runtime_mark_last_busy(&chip->client->dev);
 653                ret = pm_runtime_put_autosuspend(&chip->client->dev);
 654        }
 655
 656        return ret;
 657}
 658
 659static int tsl2583_read_raw(struct iio_dev *indio_dev,
 660                            struct iio_chan_spec const *chan,
 661                            int *val, int *val2, long mask)
 662{
 663        struct tsl2583_chip *chip = iio_priv(indio_dev);
 664        int ret, pm_ret;
 665
 666        ret = tsl2583_set_pm_runtime_busy(chip, true);
 667        if (ret < 0)
 668                return ret;
 669
 670        mutex_lock(&chip->als_mutex);
 671
 672        ret = -EINVAL;
 673        switch (mask) {
 674        case IIO_CHAN_INFO_RAW:
 675                if (chan->type == IIO_LIGHT) {
 676                        ret = tsl2583_get_lux(indio_dev);
 677                        if (ret < 0)
 678                                goto read_done;
 679
 680                        /*
 681                         * From page 20 of the TSL2581, TSL2583 data
 682                         * sheet (TAOS134 − MARCH 2011):
 683                         *
 684                         * One of the photodiodes (channel 0) is
 685                         * sensitive to both visible and infrared light,
 686                         * while the second photodiode (channel 1) is
 687                         * sensitive primarily to infrared light.
 688                         */
 689                        if (chan->channel2 == IIO_MOD_LIGHT_BOTH)
 690                                *val = chip->als_cur_info.als_ch0;
 691                        else
 692                                *val = chip->als_cur_info.als_ch1;
 693
 694                        ret = IIO_VAL_INT;
 695                }
 696                break;
 697        case IIO_CHAN_INFO_PROCESSED:
 698                if (chan->type == IIO_LIGHT) {
 699                        ret = tsl2583_get_lux(indio_dev);
 700                        if (ret < 0)
 701                                goto read_done;
 702
 703                        *val = ret;
 704                        ret = IIO_VAL_INT;
 705                }
 706                break;
 707        case IIO_CHAN_INFO_CALIBBIAS:
 708                if (chan->type == IIO_LIGHT) {
 709                        *val = chip->als_settings.als_gain_trim;
 710                        ret = IIO_VAL_INT;
 711                }
 712                break;
 713        case IIO_CHAN_INFO_CALIBSCALE:
 714                if (chan->type == IIO_LIGHT) {
 715                        *val = gainadj[chip->als_settings.als_gain].mean;
 716                        ret = IIO_VAL_INT;
 717                }
 718                break;
 719        case IIO_CHAN_INFO_INT_TIME:
 720                if (chan->type == IIO_LIGHT) {
 721                        *val = 0;
 722                        *val2 = chip->als_settings.als_time;
 723                        ret = IIO_VAL_INT_PLUS_MICRO;
 724                }
 725                break;
 726        default:
 727                break;
 728        }
 729
 730read_done:
 731        mutex_unlock(&chip->als_mutex);
 732
 733        if (ret < 0)
 734                return ret;
 735
 736        /*
 737         * Preserve the ret variable if the call to
 738         * tsl2583_set_pm_runtime_busy() is successful so the reading
 739         * (if applicable) is returned to user space.
 740         */
 741        pm_ret = tsl2583_set_pm_runtime_busy(chip, false);
 742        if (pm_ret < 0)
 743                return pm_ret;
 744
 745        return ret;
 746}
 747
 748static int tsl2583_write_raw(struct iio_dev *indio_dev,
 749                             struct iio_chan_spec const *chan,
 750                             int val, int val2, long mask)
 751{
 752        struct tsl2583_chip *chip = iio_priv(indio_dev);
 753        int ret;
 754
 755        ret = tsl2583_set_pm_runtime_busy(chip, true);
 756        if (ret < 0)
 757                return ret;
 758
 759        mutex_lock(&chip->als_mutex);
 760
 761        ret = -EINVAL;
 762        switch (mask) {
 763        case IIO_CHAN_INFO_CALIBBIAS:
 764                if (chan->type == IIO_LIGHT) {
 765                        chip->als_settings.als_gain_trim = val;
 766                        ret = 0;
 767                }
 768                break;
 769        case IIO_CHAN_INFO_CALIBSCALE:
 770                if (chan->type == IIO_LIGHT) {
 771                        unsigned int i;
 772
 773                        for (i = 0; i < ARRAY_SIZE(gainadj); i++) {
 774                                if (gainadj[i].mean == val) {
 775                                        chip->als_settings.als_gain = i;
 776                                        ret = tsl2583_set_als_gain(chip);
 777                                        break;
 778                                }
 779                        }
 780                }
 781                break;
 782        case IIO_CHAN_INFO_INT_TIME:
 783                if (chan->type == IIO_LIGHT && !val && val2 >= 50 &&
 784                    val2 <= 650 && !(val2 % 50)) {
 785                        chip->als_settings.als_time = val2;
 786                        ret = tsl2583_set_als_time(chip);
 787                }
 788                break;
 789        default:
 790                break;
 791        }
 792
 793        mutex_unlock(&chip->als_mutex);
 794
 795        if (ret < 0)
 796                return ret;
 797
 798        ret = tsl2583_set_pm_runtime_busy(chip, false);
 799        if (ret < 0)
 800                return ret;
 801
 802        return ret;
 803}
 804
 805static const struct iio_info tsl2583_info = {
 806        .attrs = &tsl2583_attribute_group,
 807        .driver_module = THIS_MODULE,
 808        .read_raw = tsl2583_read_raw,
 809        .write_raw = tsl2583_write_raw,
 810};
 811
 812static int tsl2583_probe(struct i2c_client *clientp,
 813                         const struct i2c_device_id *idp)
 814{
 815        int ret;
 816        struct tsl2583_chip *chip;
 817        struct iio_dev *indio_dev;
 818
 819        if (!i2c_check_functionality(clientp->adapter,
 820                                     I2C_FUNC_SMBUS_BYTE_DATA)) {
 821                dev_err(&clientp->dev, "%s: i2c smbus byte data functionality is unsupported\n",
 822                        __func__);
 823                return -EOPNOTSUPP;
 824        }
 825
 826        indio_dev = devm_iio_device_alloc(&clientp->dev, sizeof(*chip));
 827        if (!indio_dev)
 828                return -ENOMEM;
 829
 830        chip = iio_priv(indio_dev);
 831        chip->client = clientp;
 832        i2c_set_clientdata(clientp, indio_dev);
 833
 834        mutex_init(&chip->als_mutex);
 835
 836        ret = i2c_smbus_read_byte_data(clientp,
 837                                       TSL2583_CMD_REG | TSL2583_CHIPID);
 838        if (ret < 0) {
 839                dev_err(&clientp->dev,
 840                        "%s: failed to read the chip ID register\n", __func__);
 841                return ret;
 842        }
 843
 844        if ((ret & TSL2583_CHIP_ID_MASK) != TSL2583_CHIP_ID) {
 845                dev_err(&clientp->dev, "%s: received an unknown chip ID %x\n",
 846                        __func__, ret);
 847                return -EINVAL;
 848        }
 849
 850        indio_dev->info = &tsl2583_info;
 851        indio_dev->channels = tsl2583_channels;
 852        indio_dev->num_channels = ARRAY_SIZE(tsl2583_channels);
 853        indio_dev->dev.parent = &clientp->dev;
 854        indio_dev->modes = INDIO_DIRECT_MODE;
 855        indio_dev->name = chip->client->name;
 856
 857        pm_runtime_enable(&clientp->dev);
 858        pm_runtime_set_autosuspend_delay(&clientp->dev,
 859                                         TSL2583_POWER_OFF_DELAY_MS);
 860        pm_runtime_use_autosuspend(&clientp->dev);
 861
 862        ret = devm_iio_device_register(indio_dev->dev.parent, indio_dev);
 863        if (ret) {
 864                dev_err(&clientp->dev, "%s: iio registration failed\n",
 865                        __func__);
 866                return ret;
 867        }
 868
 869        /* Load up the V2 defaults (these are hard coded defaults for now) */
 870        tsl2583_defaults(chip);
 871
 872        dev_info(&clientp->dev, "Light sensor found.\n");
 873
 874        return 0;
 875}
 876
 877static int tsl2583_remove(struct i2c_client *client)
 878{
 879        struct iio_dev *indio_dev = i2c_get_clientdata(client);
 880        struct tsl2583_chip *chip = iio_priv(indio_dev);
 881
 882        iio_device_unregister(indio_dev);
 883
 884        pm_runtime_disable(&client->dev);
 885        pm_runtime_set_suspended(&client->dev);
 886        pm_runtime_put_noidle(&client->dev);
 887
 888        return tsl2583_set_power_state(chip, TSL2583_CNTL_PWR_OFF);
 889}
 890
 891static int __maybe_unused tsl2583_suspend(struct device *dev)
 892{
 893        struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
 894        struct tsl2583_chip *chip = iio_priv(indio_dev);
 895        int ret;
 896
 897        mutex_lock(&chip->als_mutex);
 898
 899        ret = tsl2583_set_power_state(chip, TSL2583_CNTL_PWR_OFF);
 900
 901        mutex_unlock(&chip->als_mutex);
 902
 903        return ret;
 904}
 905
 906static int __maybe_unused tsl2583_resume(struct device *dev)
 907{
 908        struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
 909        struct tsl2583_chip *chip = iio_priv(indio_dev);
 910        int ret;
 911
 912        mutex_lock(&chip->als_mutex);
 913
 914        ret = tsl2583_chip_init_and_power_on(indio_dev);
 915
 916        mutex_unlock(&chip->als_mutex);
 917
 918        return ret;
 919}
 920
 921static const struct dev_pm_ops tsl2583_pm_ops = {
 922        SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
 923                                pm_runtime_force_resume)
 924        SET_RUNTIME_PM_OPS(tsl2583_suspend, tsl2583_resume, NULL)
 925};
 926
 927static const struct i2c_device_id tsl2583_idtable[] = {
 928        { "tsl2580", 0 },
 929        { "tsl2581", 1 },
 930        { "tsl2583", 2 },
 931        {}
 932};
 933MODULE_DEVICE_TABLE(i2c, tsl2583_idtable);
 934
 935static const struct of_device_id tsl2583_of_match[] = {
 936        { .compatible = "amstaos,tsl2580", },
 937        { .compatible = "amstaos,tsl2581", },
 938        { .compatible = "amstaos,tsl2583", },
 939        { },
 940};
 941MODULE_DEVICE_TABLE(of, tsl2583_of_match);
 942
 943/* Driver definition */
 944static struct i2c_driver tsl2583_driver = {
 945        .driver = {
 946                .name = "tsl2583",
 947                .pm = &tsl2583_pm_ops,
 948                .of_match_table = tsl2583_of_match,
 949        },
 950        .id_table = tsl2583_idtable,
 951        .probe = tsl2583_probe,
 952        .remove = tsl2583_remove,
 953};
 954module_i2c_driver(tsl2583_driver);
 955
 956MODULE_AUTHOR("J. August Brenner <jbrenner@taosinc.com>");
 957MODULE_AUTHOR("Brian Masney <masneyb@onstation.org>");
 958MODULE_DESCRIPTION("TAOS tsl2583 ambient light sensor driver");
 959MODULE_LICENSE("GPL");
 960