linux/drivers/staging/iio/light/tsl2x7x_core.c
<<
>>
Prefs
   1/*
   2 * Device driver for monitoring ambient light intensity in (lux)
   3 * and proximity detection (prox) within the TAOS TSL2X7X family of devices.
   4 *
   5 * Copyright (c) 2012, TAOS Corporation.
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License as published by
   9 * the Free Software Foundation; either version 2 of the License, or
  10 * (at your option) any later version.
  11 *
  12 * This program is distributed in the hope that it will be useful, but WITHOUT
  13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  15 * more details.
  16 *
  17 * You should have received a copy of the GNU General Public License along
  18 * with this program; if not, write to the Free Software Foundation, Inc.,
  19 * 51 Franklin Street, Fifth Floor, Boston, MA        02110-1301, USA.
  20 */
  21
  22#include <linux/kernel.h>
  23#include <linux/i2c.h>
  24#include <linux/errno.h>
  25#include <linux/delay.h>
  26#include <linux/mutex.h>
  27#include <linux/interrupt.h>
  28#include <linux/slab.h>
  29#include <linux/module.h>
  30#include <linux/iio/events.h>
  31#include <linux/iio/iio.h>
  32#include <linux/iio/sysfs.h>
  33#include "tsl2x7x.h"
  34
  35/* Cal defs*/
  36#define PROX_STAT_CAL        0
  37#define PROX_STAT_SAMP       1
  38#define MAX_SAMPLES_CAL      200
  39
  40/* TSL2X7X Device ID */
  41#define TRITON_ID    0x00
  42#define SWORDFISH_ID 0x30
  43#define HALIBUT_ID   0x20
  44
  45/* Lux calculation constants */
  46#define TSL2X7X_LUX_CALC_OVER_FLOW     65535
  47
  48/* TAOS Register definitions - note:
  49 * depending on device, some of these register are not used and the
  50 * register address is benign.
  51 */
  52/* 2X7X register offsets */
  53#define TSL2X7X_MAX_CONFIG_REG         16
  54
  55/* Device Registers and Masks */
  56#define TSL2X7X_CNTRL                  0x00
  57#define TSL2X7X_ALS_TIME               0X01
  58#define TSL2X7X_PRX_TIME               0x02
  59#define TSL2X7X_WAIT_TIME              0x03
  60#define TSL2X7X_ALS_MINTHRESHLO        0X04
  61#define TSL2X7X_ALS_MINTHRESHHI        0X05
  62#define TSL2X7X_ALS_MAXTHRESHLO        0X06
  63#define TSL2X7X_ALS_MAXTHRESHHI        0X07
  64#define TSL2X7X_PRX_MINTHRESHLO        0X08
  65#define TSL2X7X_PRX_MINTHRESHHI        0X09
  66#define TSL2X7X_PRX_MAXTHRESHLO        0X0A
  67#define TSL2X7X_PRX_MAXTHRESHHI        0X0B
  68#define TSL2X7X_PERSISTENCE            0x0C
  69#define TSL2X7X_PRX_CONFIG             0x0D
  70#define TSL2X7X_PRX_COUNT              0x0E
  71#define TSL2X7X_GAIN                   0x0F
  72#define TSL2X7X_NOTUSED                0x10
  73#define TSL2X7X_REVID                  0x11
  74#define TSL2X7X_CHIPID                 0x12
  75#define TSL2X7X_STATUS                 0x13
  76#define TSL2X7X_ALS_CHAN0LO            0x14
  77#define TSL2X7X_ALS_CHAN0HI            0x15
  78#define TSL2X7X_ALS_CHAN1LO            0x16
  79#define TSL2X7X_ALS_CHAN1HI            0x17
  80#define TSL2X7X_PRX_LO                 0x18
  81#define TSL2X7X_PRX_HI                 0x19
  82
  83/* tsl2X7X cmd reg masks */
  84#define TSL2X7X_CMD_REG                0x80
  85#define TSL2X7X_CMD_SPL_FN             0x60
  86
  87#define TSL2X7X_CMD_PROX_INT_CLR       0X05
  88#define TSL2X7X_CMD_ALS_INT_CLR        0x06
  89#define TSL2X7X_CMD_PROXALS_INT_CLR    0X07
  90
  91/* tsl2X7X cntrl reg masks */
  92#define TSL2X7X_CNTL_ADC_ENBL          0x02
  93#define TSL2X7X_CNTL_PWR_ON            0x01
  94
  95/* tsl2X7X status reg masks */
  96#define TSL2X7X_STA_ADC_VALID          0x01
  97#define TSL2X7X_STA_PRX_VALID          0x02
  98#define TSL2X7X_STA_ADC_PRX_VALID      (TSL2X7X_STA_ADC_VALID |\
  99                                        TSL2X7X_STA_PRX_VALID)
 100#define TSL2X7X_STA_ALS_INTR           0x10
 101#define TSL2X7X_STA_PRX_INTR           0x20
 102
 103/* tsl2X7X cntrl reg masks */
 104#define TSL2X7X_CNTL_REG_CLEAR         0x00
 105#define TSL2X7X_CNTL_PROX_INT_ENBL     0X20
 106#define TSL2X7X_CNTL_ALS_INT_ENBL      0X10
 107#define TSL2X7X_CNTL_WAIT_TMR_ENBL     0X08
 108#define TSL2X7X_CNTL_PROX_DET_ENBL     0X04
 109#define TSL2X7X_CNTL_PWRON             0x01
 110#define TSL2X7X_CNTL_ALSPON_ENBL       0x03
 111#define TSL2X7X_CNTL_INTALSPON_ENBL    0x13
 112#define TSL2X7X_CNTL_PROXPON_ENBL      0x0F
 113#define TSL2X7X_CNTL_INTPROXPON_ENBL   0x2F
 114
 115/*Prox diode to use */
 116#define TSL2X7X_DIODE0                 0x10
 117#define TSL2X7X_DIODE1                 0x20
 118#define TSL2X7X_DIODE_BOTH             0x30
 119
 120/* LED Power */
 121#define TSL2X7X_mA100                  0x00
 122#define TSL2X7X_mA50                   0x40
 123#define TSL2X7X_mA25                   0x80
 124#define TSL2X7X_mA13                   0xD0
 125#define TSL2X7X_MAX_TIMER_CNT          (0xFF)
 126
 127#define TSL2X7X_MIN_ITIME 3
 128
 129/* TAOS txx2x7x Device family members */
 130enum {
 131        tsl2571,
 132        tsl2671,
 133        tmd2671,
 134        tsl2771,
 135        tmd2771,
 136        tsl2572,
 137        tsl2672,
 138        tmd2672,
 139        tsl2772,
 140        tmd2772
 141};
 142
 143enum {
 144        TSL2X7X_CHIP_UNKNOWN = 0,
 145        TSL2X7X_CHIP_WORKING = 1,
 146        TSL2X7X_CHIP_SUSPENDED = 2
 147};
 148
 149struct tsl2x7x_parse_result {
 150        int integer;
 151        int fract;
 152};
 153
 154/* Per-device data */
 155struct tsl2x7x_als_info {
 156        u16 als_ch0;
 157        u16 als_ch1;
 158        u16 lux;
 159};
 160
 161struct tsl2x7x_prox_stat {
 162        int min;
 163        int max;
 164        int mean;
 165        unsigned long stddev;
 166};
 167
 168struct tsl2x7x_chip_info {
 169        int chan_table_elements;
 170        struct iio_chan_spec            channel[4];
 171        const struct iio_info           *info;
 172};
 173
 174struct tsl2X7X_chip {
 175        kernel_ulong_t id;
 176        struct mutex prox_mutex;
 177        struct mutex als_mutex;
 178        struct i2c_client *client;
 179        u16 prox_data;
 180        struct tsl2x7x_als_info als_cur_info;
 181        struct tsl2x7x_settings tsl2x7x_settings;
 182        struct tsl2X7X_platform_data *pdata;
 183        int als_time_scale;
 184        int als_saturation;
 185        int tsl2x7x_chip_status;
 186        u8 tsl2x7x_config[TSL2X7X_MAX_CONFIG_REG];
 187        const struct tsl2x7x_chip_info  *chip_info;
 188        const struct iio_info *info;
 189        s64 event_timestamp;
 190        /* This structure is intentionally large to accommodate
 191         * updates via sysfs. */
 192        /* Sized to 9 = max 8 segments + 1 termination segment */
 193        struct tsl2x7x_lux tsl2x7x_device_lux[TSL2X7X_MAX_LUX_TABLE_SIZE];
 194};
 195
 196/* Different devices require different coefficents */
 197static const struct tsl2x7x_lux tsl2x71_lux_table[] = {
 198        { 14461,   611,   1211 },
 199        { 18540,   352,    623 },
 200        {     0,     0,      0 },
 201};
 202
 203static const struct tsl2x7x_lux tmd2x71_lux_table[] = {
 204        { 11635,   115,    256 },
 205        { 15536,    87,    179 },
 206        {     0,     0,      0 },
 207};
 208
 209static const struct tsl2x7x_lux tsl2x72_lux_table[] = {
 210        { 14013,   466,   917 },
 211        { 18222,   310,   552 },
 212        {     0,     0,     0 },
 213};
 214
 215static const struct tsl2x7x_lux tmd2x72_lux_table[] = {
 216        { 13218,   130,   262 },
 217        { 17592,   92,    169 },
 218        {     0,     0,     0 },
 219};
 220
 221static const struct tsl2x7x_lux *tsl2x7x_default_lux_table_group[] = {
 222        [tsl2571] =     tsl2x71_lux_table,
 223        [tsl2671] =     tsl2x71_lux_table,
 224        [tmd2671] =     tmd2x71_lux_table,
 225        [tsl2771] =     tsl2x71_lux_table,
 226        [tmd2771] =     tmd2x71_lux_table,
 227        [tsl2572] =     tsl2x72_lux_table,
 228        [tsl2672] =     tsl2x72_lux_table,
 229        [tmd2672] =     tmd2x72_lux_table,
 230        [tsl2772] =     tsl2x72_lux_table,
 231        [tmd2772] =     tmd2x72_lux_table,
 232};
 233
 234static const struct tsl2x7x_settings tsl2x7x_default_settings = {
 235        .als_time = 219, /* 101 ms */
 236        .als_gain = 0,
 237        .prx_time = 254, /* 5.4 ms */
 238        .prox_gain = 1,
 239        .wait_time = 245,
 240        .prox_config = 0,
 241        .als_gain_trim = 1000,
 242        .als_cal_target = 150,
 243        .als_thresh_low = 200,
 244        .als_thresh_high = 256,
 245        .persistence = 255,
 246        .interrupts_en = 0,
 247        .prox_thres_low  = 0,
 248        .prox_thres_high = 512,
 249        .prox_max_samples_cal = 30,
 250        .prox_pulse_count = 8
 251};
 252
 253static const s16 tsl2X7X_als_gainadj[] = {
 254        1,
 255        8,
 256        16,
 257        120
 258};
 259
 260static const s16 tsl2X7X_prx_gainadj[] = {
 261        1,
 262        2,
 263        4,
 264        8
 265};
 266
 267/* Channel variations */
 268enum {
 269        ALS,
 270        PRX,
 271        ALSPRX,
 272        PRX2,
 273        ALSPRX2,
 274};
 275
 276static const u8 device_channel_config[] = {
 277        ALS,
 278        PRX,
 279        PRX,
 280        ALSPRX,
 281        ALSPRX,
 282        ALS,
 283        PRX2,
 284        PRX2,
 285        ALSPRX2,
 286        ALSPRX2
 287};
 288
 289/**
 290 * tsl2x7x_i2c_read() - Read a byte from a register.
 291 * @client:     i2c client
 292 * @reg:        device register to read from
 293 * @*val:       pointer to location to store register contents.
 294 *
 295 */
 296static int
 297tsl2x7x_i2c_read(struct i2c_client *client, u8 reg, u8 *val)
 298{
 299        int ret;
 300
 301        /* select register to write */
 302        ret = i2c_smbus_write_byte(client, (TSL2X7X_CMD_REG | reg));
 303        if (ret < 0) {
 304                dev_err(&client->dev, "failed to write register %x\n", reg);
 305                return ret;
 306        }
 307
 308        /* read the data */
 309        ret = i2c_smbus_read_byte(client);
 310        if (ret >= 0)
 311                *val = (u8)ret;
 312        else
 313                dev_err(&client->dev, "failed to read register %x\n", reg);
 314
 315        return ret;
 316}
 317
 318/**
 319 * tsl2x7x_get_lux() - Reads and calculates current lux value.
 320 * @indio_dev:  pointer to IIO device
 321 *
 322 * The raw ch0 and ch1 values of the ambient light sensed in the last
 323 * integration cycle are read from the device.
 324 * Time scale factor array values are adjusted based on the integration time.
 325 * The raw values are multiplied by a scale factor, and device gain is obtained
 326 * using gain index. Limit checks are done next, then the ratio of a multiple
 327 * of ch1 value, to the ch0 value, is calculated. Array tsl2x7x_device_lux[]
 328 * is then scanned to find the first ratio value that is just above the ratio
 329 * we just calculated. The ch0 and ch1 multiplier constants in the array are
 330 * then used along with the time scale factor array values, to calculate the
 331 * lux.
 332 */
 333static int tsl2x7x_get_lux(struct iio_dev *indio_dev)
 334{
 335        u16 ch0, ch1; /* separated ch0/ch1 data from device */
 336        u32 lux; /* raw lux calculated from device data */
 337        u64 lux64;
 338        u32 ratio;
 339        u8 buf[4];
 340        struct tsl2x7x_lux *p;
 341        struct tsl2X7X_chip *chip = iio_priv(indio_dev);
 342        int i, ret;
 343        u32 ch0lux = 0;
 344        u32 ch1lux = 0;
 345
 346        if (mutex_trylock(&chip->als_mutex) == 0)
 347                return chip->als_cur_info.lux; /* busy, so return LAST VALUE */
 348
 349        if (chip->tsl2x7x_chip_status != TSL2X7X_CHIP_WORKING) {
 350                /* device is not enabled */
 351                dev_err(&chip->client->dev, "%s: device is not enabled\n",
 352                                __func__);
 353                ret = -EBUSY;
 354                goto out_unlock;
 355        }
 356
 357        ret = tsl2x7x_i2c_read(chip->client,
 358                (TSL2X7X_CMD_REG | TSL2X7X_STATUS), &buf[0]);
 359        if (ret < 0) {
 360                dev_err(&chip->client->dev,
 361                        "%s: Failed to read STATUS Reg\n", __func__);
 362                goto out_unlock;
 363        }
 364        /* is data new & valid */
 365        if (!(buf[0] & TSL2X7X_STA_ADC_VALID)) {
 366                dev_err(&chip->client->dev,
 367                        "%s: data not valid yet\n", __func__);
 368                ret = chip->als_cur_info.lux; /* return LAST VALUE */
 369                goto out_unlock;
 370        }
 371
 372        for (i = 0; i < 4; i++) {
 373                ret = tsl2x7x_i2c_read(chip->client,
 374                        (TSL2X7X_CMD_REG | (TSL2X7X_ALS_CHAN0LO + i)),
 375                        &buf[i]);
 376                if (ret < 0) {
 377                        dev_err(&chip->client->dev,
 378                                "failed to read. err=%x\n", ret);
 379                        goto out_unlock;
 380                }
 381        }
 382
 383        /* clear any existing interrupt status */
 384        ret = i2c_smbus_write_byte(chip->client,
 385                (TSL2X7X_CMD_REG |
 386                                TSL2X7X_CMD_SPL_FN |
 387                                TSL2X7X_CMD_ALS_INT_CLR));
 388        if (ret < 0) {
 389                dev_err(&chip->client->dev,
 390                        "i2c_write_command failed - err = %d\n", ret);
 391                goto out_unlock; /* have no data, so return failure */
 392        }
 393
 394        /* extract ALS/lux data */
 395        ch0 = le16_to_cpup((const __le16 *)&buf[0]);
 396        ch1 = le16_to_cpup((const __le16 *)&buf[2]);
 397
 398        chip->als_cur_info.als_ch0 = ch0;
 399        chip->als_cur_info.als_ch1 = ch1;
 400
 401        if ((ch0 >= chip->als_saturation) || (ch1 >= chip->als_saturation)) {
 402                lux = TSL2X7X_LUX_CALC_OVER_FLOW;
 403                goto return_max;
 404        }
 405
 406        if (!ch0) {
 407                /* have no data, so return LAST VALUE */
 408                ret = chip->als_cur_info.lux;
 409                goto out_unlock;
 410        }
 411        /* calculate ratio */
 412        ratio = (ch1 << 15) / ch0;
 413        /* convert to unscaled lux using the pointer to the table */
 414        p = (struct tsl2x7x_lux *) chip->tsl2x7x_device_lux;
 415        while (p->ratio != 0 && p->ratio < ratio)
 416                p++;
 417
 418        if (p->ratio == 0) {
 419                lux = 0;
 420        } else {
 421                ch0lux = DIV_ROUND_UP(ch0 * p->ch0,
 422                        tsl2X7X_als_gainadj[chip->tsl2x7x_settings.als_gain]);
 423                ch1lux = DIV_ROUND_UP(ch1 * p->ch1,
 424                        tsl2X7X_als_gainadj[chip->tsl2x7x_settings.als_gain]);
 425                lux = ch0lux - ch1lux;
 426        }
 427
 428        /* note: lux is 31 bit max at this point */
 429        if (ch1lux > ch0lux) {
 430                dev_dbg(&chip->client->dev, "ch1lux > ch0lux-return last value\n");
 431                ret = chip->als_cur_info.lux;
 432                goto out_unlock;
 433        }
 434
 435        /* adjust for active time scale */
 436        if (chip->als_time_scale == 0)
 437                lux = 0;
 438        else
 439                lux = (lux + (chip->als_time_scale >> 1)) /
 440                        chip->als_time_scale;
 441
 442        /* adjust for active gain scale
 443         * The tsl2x7x_device_lux tables have a factor of 256 built-in.
 444         * User-specified gain provides a multiplier.
 445         * Apply user-specified gain before shifting right to retain precision.
 446         * Use 64 bits to avoid overflow on multiplication.
 447         * Then go back to 32 bits before division to avoid using div_u64().
 448         */
 449
 450        lux64 = lux;
 451        lux64 = lux64 * chip->tsl2x7x_settings.als_gain_trim;
 452        lux64 >>= 8;
 453        lux = lux64;
 454        lux = (lux + 500) / 1000;
 455
 456        if (lux > TSL2X7X_LUX_CALC_OVER_FLOW) /* check for overflow */
 457                lux = TSL2X7X_LUX_CALC_OVER_FLOW;
 458
 459        /* Update the structure with the latest lux. */
 460return_max:
 461        chip->als_cur_info.lux = lux;
 462        ret = lux;
 463
 464out_unlock:
 465        mutex_unlock(&chip->als_mutex);
 466
 467        return ret;
 468}
 469
 470/**
 471 * tsl2x7x_get_prox() - Reads proximity data registers and updates
 472 *                      chip->prox_data.
 473 *
 474 * @indio_dev:  pointer to IIO device
 475 */
 476static int tsl2x7x_get_prox(struct iio_dev *indio_dev)
 477{
 478        int i;
 479        int ret;
 480        u8 status;
 481        u8 chdata[2];
 482        struct tsl2X7X_chip *chip = iio_priv(indio_dev);
 483
 484        if (mutex_trylock(&chip->prox_mutex) == 0) {
 485                dev_err(&chip->client->dev,
 486                        "%s: Can't get prox mutex\n", __func__);
 487                return -EBUSY;
 488        }
 489
 490        ret = tsl2x7x_i2c_read(chip->client,
 491                (TSL2X7X_CMD_REG | TSL2X7X_STATUS), &status);
 492        if (ret < 0) {
 493                dev_err(&chip->client->dev, "i2c err=%d\n", ret);
 494                goto prox_poll_err;
 495        }
 496
 497        switch (chip->id) {
 498        case tsl2571:
 499        case tsl2671:
 500        case tmd2671:
 501        case tsl2771:
 502        case tmd2771:
 503                if (!(status & TSL2X7X_STA_ADC_VALID))
 504                        goto prox_poll_err;
 505        break;
 506        case tsl2572:
 507        case tsl2672:
 508        case tmd2672:
 509        case tsl2772:
 510        case tmd2772:
 511                if (!(status & TSL2X7X_STA_PRX_VALID))
 512                        goto prox_poll_err;
 513        break;
 514        }
 515
 516        for (i = 0; i < 2; i++) {
 517                ret = tsl2x7x_i2c_read(chip->client,
 518                        (TSL2X7X_CMD_REG |
 519                                        (TSL2X7X_PRX_LO + i)), &chdata[i]);
 520                if (ret < 0)
 521                        goto prox_poll_err;
 522        }
 523
 524        chip->prox_data =
 525                        le16_to_cpup((const __le16 *)&chdata[0]);
 526
 527prox_poll_err:
 528
 529        mutex_unlock(&chip->prox_mutex);
 530
 531        return chip->prox_data;
 532}
 533
 534/**
 535 * tsl2x7x_defaults() - Populates the device nominal operating parameters
 536 *                      with those provided by a 'platform' data struct or
 537 *                      with prefined defaults.
 538 *
 539 * @chip:               pointer to device structure.
 540 */
 541static void tsl2x7x_defaults(struct tsl2X7X_chip *chip)
 542{
 543        /* If Operational settings defined elsewhere.. */
 544        if (chip->pdata && chip->pdata->platform_default_settings)
 545                memcpy(&(chip->tsl2x7x_settings),
 546                        chip->pdata->platform_default_settings,
 547                        sizeof(tsl2x7x_default_settings));
 548        else
 549                memcpy(&(chip->tsl2x7x_settings),
 550                        &tsl2x7x_default_settings,
 551                        sizeof(tsl2x7x_default_settings));
 552
 553        /* Load up the proper lux table. */
 554        if (chip->pdata && chip->pdata->platform_lux_table[0].ratio != 0)
 555                memcpy(chip->tsl2x7x_device_lux,
 556                        chip->pdata->platform_lux_table,
 557                        sizeof(chip->pdata->platform_lux_table));
 558        else
 559                memcpy(chip->tsl2x7x_device_lux,
 560                (struct tsl2x7x_lux *)tsl2x7x_default_lux_table_group[chip->id],
 561                                MAX_DEFAULT_TABLE_BYTES);
 562}
 563
 564/**
 565 * tsl2x7x_als_calibrate() -    Obtain single reading and calculate
 566 *                              the als_gain_trim.
 567 *
 568 * @indio_dev:  pointer to IIO device
 569 */
 570static int tsl2x7x_als_calibrate(struct iio_dev *indio_dev)
 571{
 572        struct tsl2X7X_chip *chip = iio_priv(indio_dev);
 573        u8 reg_val;
 574        int gain_trim_val;
 575        int ret;
 576        int lux_val;
 577
 578        ret = i2c_smbus_write_byte(chip->client,
 579                        (TSL2X7X_CMD_REG | TSL2X7X_CNTRL));
 580        if (ret < 0) {
 581                dev_err(&chip->client->dev,
 582                        "failed to write CNTRL register, ret=%d\n", ret);
 583                return ret;
 584        }
 585
 586        reg_val = i2c_smbus_read_byte(chip->client);
 587        if ((reg_val & (TSL2X7X_CNTL_ADC_ENBL | TSL2X7X_CNTL_PWR_ON))
 588                != (TSL2X7X_CNTL_ADC_ENBL | TSL2X7X_CNTL_PWR_ON)) {
 589                dev_err(&chip->client->dev,
 590                        "%s: failed: ADC not enabled\n", __func__);
 591                return -1;
 592        }
 593
 594        ret = i2c_smbus_write_byte(chip->client,
 595                        (TSL2X7X_CMD_REG | TSL2X7X_CNTRL));
 596        if (ret < 0) {
 597                dev_err(&chip->client->dev,
 598                        "failed to write ctrl reg: ret=%d\n", ret);
 599                return ret;
 600        }
 601
 602        reg_val = i2c_smbus_read_byte(chip->client);
 603        if ((reg_val & TSL2X7X_STA_ADC_VALID) != TSL2X7X_STA_ADC_VALID) {
 604                dev_err(&chip->client->dev,
 605                        "%s: failed: STATUS - ADC not valid.\n", __func__);
 606                return -ENODATA;
 607        }
 608
 609        lux_val = tsl2x7x_get_lux(indio_dev);
 610        if (lux_val < 0) {
 611                dev_err(&chip->client->dev,
 612                "%s: failed to get lux\n", __func__);
 613                return lux_val;
 614        }
 615
 616        gain_trim_val =  ((chip->tsl2x7x_settings.als_cal_target)
 617                        * chip->tsl2x7x_settings.als_gain_trim) / lux_val;
 618        if ((gain_trim_val < 250) || (gain_trim_val > 4000))
 619                return -ERANGE;
 620
 621        chip->tsl2x7x_settings.als_gain_trim = gain_trim_val;
 622        dev_info(&chip->client->dev,
 623                "%s als_calibrate completed\n", chip->client->name);
 624
 625        return (int) gain_trim_val;
 626}
 627
 628static int tsl2x7x_chip_on(struct iio_dev *indio_dev)
 629{
 630        int i;
 631        int ret = 0;
 632        u8 *dev_reg;
 633        u8 utmp;
 634        int als_count;
 635        int als_time;
 636        struct tsl2X7X_chip *chip = iio_priv(indio_dev);
 637        u8 reg_val = 0;
 638
 639        if (chip->pdata && chip->pdata->power_on)
 640                chip->pdata->power_on(indio_dev);
 641
 642        /* Non calculated parameters */
 643        chip->tsl2x7x_config[TSL2X7X_PRX_TIME] =
 644                        chip->tsl2x7x_settings.prx_time;
 645        chip->tsl2x7x_config[TSL2X7X_WAIT_TIME] =
 646                        chip->tsl2x7x_settings.wait_time;
 647        chip->tsl2x7x_config[TSL2X7X_PRX_CONFIG] =
 648                        chip->tsl2x7x_settings.prox_config;
 649
 650        chip->tsl2x7x_config[TSL2X7X_ALS_MINTHRESHLO] =
 651                (chip->tsl2x7x_settings.als_thresh_low) & 0xFF;
 652        chip->tsl2x7x_config[TSL2X7X_ALS_MINTHRESHHI] =
 653                (chip->tsl2x7x_settings.als_thresh_low >> 8) & 0xFF;
 654        chip->tsl2x7x_config[TSL2X7X_ALS_MAXTHRESHLO] =
 655                (chip->tsl2x7x_settings.als_thresh_high) & 0xFF;
 656        chip->tsl2x7x_config[TSL2X7X_ALS_MAXTHRESHHI] =
 657                (chip->tsl2x7x_settings.als_thresh_high >> 8) & 0xFF;
 658        chip->tsl2x7x_config[TSL2X7X_PERSISTENCE] =
 659                chip->tsl2x7x_settings.persistence;
 660
 661        chip->tsl2x7x_config[TSL2X7X_PRX_COUNT] =
 662                        chip->tsl2x7x_settings.prox_pulse_count;
 663        chip->tsl2x7x_config[TSL2X7X_PRX_MINTHRESHLO] =
 664                        (chip->tsl2x7x_settings.prox_thres_low) & 0xFF;
 665        chip->tsl2x7x_config[TSL2X7X_PRX_MINTHRESHHI] =
 666                        (chip->tsl2x7x_settings.prox_thres_low >> 8) & 0xFF;
 667        chip->tsl2x7x_config[TSL2X7X_PRX_MAXTHRESHLO] =
 668                        (chip->tsl2x7x_settings.prox_thres_high) & 0xFF;
 669        chip->tsl2x7x_config[TSL2X7X_PRX_MAXTHRESHHI] =
 670                        (chip->tsl2x7x_settings.prox_thres_high >> 8) & 0xFF;
 671
 672        /* and make sure we're not already on */
 673        if (chip->tsl2x7x_chip_status == TSL2X7X_CHIP_WORKING) {
 674                /* if forcing a register update - turn off, then on */
 675                dev_info(&chip->client->dev, "device is already enabled\n");
 676                return -EINVAL;
 677        }
 678
 679        /* determine als integration register */
 680        als_count = (chip->tsl2x7x_settings.als_time * 100 + 135) / 270;
 681        if (!als_count)
 682                als_count = 1; /* ensure at least one cycle */
 683
 684        /* convert back to time (encompasses overrides) */
 685        als_time = (als_count * 27 + 5) / 10;
 686        chip->tsl2x7x_config[TSL2X7X_ALS_TIME] = 256 - als_count;
 687
 688        /* Set the gain based on tsl2x7x_settings struct */
 689        chip->tsl2x7x_config[TSL2X7X_GAIN] =
 690                chip->tsl2x7x_settings.als_gain |
 691                        (TSL2X7X_mA100 | TSL2X7X_DIODE1)
 692                        | ((chip->tsl2x7x_settings.prox_gain) << 2);
 693
 694        /* set chip struct re scaling and saturation */
 695        chip->als_saturation = als_count * 922; /* 90% of full scale */
 696        chip->als_time_scale = (als_time + 25) / 50;
 697
 698        /* TSL2X7X Specific power-on / adc enable sequence
 699         * Power on the device 1st. */
 700        utmp = TSL2X7X_CNTL_PWR_ON;
 701        ret = i2c_smbus_write_byte_data(chip->client,
 702                TSL2X7X_CMD_REG | TSL2X7X_CNTRL, utmp);
 703        if (ret < 0) {
 704                dev_err(&chip->client->dev,
 705                        "%s: failed on CNTRL reg.\n", __func__);
 706                return ret;
 707        }
 708
 709        /* Use the following shadow copy for our delay before enabling ADC.
 710         * Write all the registers. */
 711        for (i = 0, dev_reg = chip->tsl2x7x_config;
 712                        i < TSL2X7X_MAX_CONFIG_REG; i++) {
 713                ret = i2c_smbus_write_byte_data(chip->client,
 714                                TSL2X7X_CMD_REG + i, *dev_reg++);
 715                if (ret < 0) {
 716                        dev_err(&chip->client->dev,
 717                                "failed on write to reg %d.\n", i);
 718                        return ret;
 719                }
 720        }
 721
 722        mdelay(3);      /* Power-on settling time */
 723
 724        /* NOW enable the ADC
 725         * initialize the desired mode of operation */
 726        utmp = TSL2X7X_CNTL_PWR_ON |
 727                        TSL2X7X_CNTL_ADC_ENBL |
 728                        TSL2X7X_CNTL_PROX_DET_ENBL;
 729        ret = i2c_smbus_write_byte_data(chip->client,
 730                        TSL2X7X_CMD_REG | TSL2X7X_CNTRL, utmp);
 731        if (ret < 0) {
 732                dev_err(&chip->client->dev,
 733                        "%s: failed on 2nd CTRL reg.\n", __func__);
 734                return ret;
 735        }
 736
 737        chip->tsl2x7x_chip_status = TSL2X7X_CHIP_WORKING;
 738
 739        if (chip->tsl2x7x_settings.interrupts_en != 0) {
 740                dev_info(&chip->client->dev, "Setting Up Interrupt(s)\n");
 741
 742                reg_val = TSL2X7X_CNTL_PWR_ON | TSL2X7X_CNTL_ADC_ENBL;
 743                if ((chip->tsl2x7x_settings.interrupts_en == 0x20) ||
 744                        (chip->tsl2x7x_settings.interrupts_en == 0x30))
 745                        reg_val |= TSL2X7X_CNTL_PROX_DET_ENBL;
 746
 747                reg_val |= chip->tsl2x7x_settings.interrupts_en;
 748                ret = i2c_smbus_write_byte_data(chip->client,
 749                        (TSL2X7X_CMD_REG | TSL2X7X_CNTRL), reg_val);
 750                if (ret < 0)
 751                        dev_err(&chip->client->dev,
 752                                "%s: failed in tsl2x7x_IOCTL_INT_SET.\n",
 753                                __func__);
 754
 755                /* Clear out any initial interrupts  */
 756                ret = i2c_smbus_write_byte(chip->client,
 757                        TSL2X7X_CMD_REG | TSL2X7X_CMD_SPL_FN |
 758                        TSL2X7X_CMD_PROXALS_INT_CLR);
 759                if (ret < 0) {
 760                        dev_err(&chip->client->dev,
 761                                "%s: Failed to clear Int status\n",
 762                                __func__);
 763                return ret;
 764                }
 765        }
 766
 767        return ret;
 768}
 769
 770static int tsl2x7x_chip_off(struct iio_dev *indio_dev)
 771{
 772        int ret;
 773        struct tsl2X7X_chip *chip = iio_priv(indio_dev);
 774
 775        /* turn device off */
 776        chip->tsl2x7x_chip_status = TSL2X7X_CHIP_SUSPENDED;
 777
 778        ret = i2c_smbus_write_byte_data(chip->client,
 779                TSL2X7X_CMD_REG | TSL2X7X_CNTRL, 0x00);
 780
 781        if (chip->pdata && chip->pdata->power_off)
 782                chip->pdata->power_off(chip->client);
 783
 784        return ret;
 785}
 786
 787/**
 788 * tsl2x7x_invoke_change
 789 * @indio_dev:  pointer to IIO device
 790 *
 791 * Obtain and lock both ALS and PROX resources,
 792 * determine and save device state (On/Off),
 793 * cycle device to implement updated parameter,
 794 * put device back into proper state, and unlock
 795 * resource.
 796 */
 797static
 798int tsl2x7x_invoke_change(struct iio_dev *indio_dev)
 799{
 800        struct tsl2X7X_chip *chip = iio_priv(indio_dev);
 801        int device_status = chip->tsl2x7x_chip_status;
 802
 803        mutex_lock(&chip->als_mutex);
 804        mutex_lock(&chip->prox_mutex);
 805
 806        if (device_status == TSL2X7X_CHIP_WORKING)
 807                tsl2x7x_chip_off(indio_dev);
 808
 809        tsl2x7x_chip_on(indio_dev);
 810
 811        if (device_status != TSL2X7X_CHIP_WORKING)
 812                tsl2x7x_chip_off(indio_dev);
 813
 814        mutex_unlock(&chip->prox_mutex);
 815        mutex_unlock(&chip->als_mutex);
 816
 817        return 0;
 818}
 819
 820static
 821void tsl2x7x_prox_calculate(int *data, int length,
 822                struct tsl2x7x_prox_stat *statP)
 823{
 824        int i;
 825        int sample_sum;
 826        int tmp;
 827
 828        if (!length)
 829                length = 1;
 830
 831        sample_sum = 0;
 832        statP->min = INT_MAX;
 833        statP->max = INT_MIN;
 834        for (i = 0; i < length; i++) {
 835                sample_sum += data[i];
 836                statP->min = min(statP->min, data[i]);
 837                statP->max = max(statP->max, data[i]);
 838        }
 839
 840        statP->mean = sample_sum / length;
 841        sample_sum = 0;
 842        for (i = 0; i < length; i++) {
 843                tmp = data[i] - statP->mean;
 844                sample_sum += tmp * tmp;
 845        }
 846        statP->stddev = int_sqrt((long)sample_sum)/length;
 847}
 848
 849/**
 850 * tsl2x7x_prox_cal() - Calculates std. and sets thresholds.
 851 * @indio_dev:  pointer to IIO device
 852 *
 853 * Calculates a standard deviation based on the samples,
 854 * and sets the threshold accordingly.
 855 */
 856static void tsl2x7x_prox_cal(struct iio_dev *indio_dev)
 857{
 858        int prox_history[MAX_SAMPLES_CAL + 1];
 859        int i;
 860        struct tsl2x7x_prox_stat prox_stat_data[2];
 861        struct tsl2x7x_prox_stat *calP;
 862        struct tsl2X7X_chip *chip = iio_priv(indio_dev);
 863        u8 tmp_irq_settings;
 864        u8 current_state = chip->tsl2x7x_chip_status;
 865
 866        if (chip->tsl2x7x_settings.prox_max_samples_cal > MAX_SAMPLES_CAL) {
 867                dev_err(&chip->client->dev,
 868                        "max prox samples cal is too big: %d\n",
 869                        chip->tsl2x7x_settings.prox_max_samples_cal);
 870                chip->tsl2x7x_settings.prox_max_samples_cal = MAX_SAMPLES_CAL;
 871        }
 872
 873        /* have to stop to change settings */
 874        tsl2x7x_chip_off(indio_dev);
 875
 876        /* Enable proximity detection save just in case prox not wanted yet*/
 877        tmp_irq_settings = chip->tsl2x7x_settings.interrupts_en;
 878        chip->tsl2x7x_settings.interrupts_en |= TSL2X7X_CNTL_PROX_INT_ENBL;
 879
 880        /*turn on device if not already on*/
 881        tsl2x7x_chip_on(indio_dev);
 882
 883        /*gather the samples*/
 884        for (i = 0; i < chip->tsl2x7x_settings.prox_max_samples_cal; i++) {
 885                mdelay(15);
 886                tsl2x7x_get_prox(indio_dev);
 887                prox_history[i] = chip->prox_data;
 888                dev_info(&chip->client->dev, "2 i=%d prox data= %d\n",
 889                        i, chip->prox_data);
 890        }
 891
 892        tsl2x7x_chip_off(indio_dev);
 893        calP = &prox_stat_data[PROX_STAT_CAL];
 894        tsl2x7x_prox_calculate(prox_history,
 895                chip->tsl2x7x_settings.prox_max_samples_cal, calP);
 896        chip->tsl2x7x_settings.prox_thres_high = (calP->max << 1) - calP->mean;
 897
 898        dev_info(&chip->client->dev, " cal min=%d mean=%d max=%d\n",
 899                calP->min, calP->mean, calP->max);
 900        dev_info(&chip->client->dev,
 901                "%s proximity threshold set to %d\n",
 902                chip->client->name, chip->tsl2x7x_settings.prox_thres_high);
 903
 904        /* back to the way they were */
 905        chip->tsl2x7x_settings.interrupts_en = tmp_irq_settings;
 906        if (current_state == TSL2X7X_CHIP_WORKING)
 907                tsl2x7x_chip_on(indio_dev);
 908}
 909
 910static ssize_t tsl2x7x_power_state_show(struct device *dev,
 911        struct device_attribute *attr, char *buf)
 912{
 913        struct tsl2X7X_chip *chip = iio_priv(dev_to_iio_dev(dev));
 914
 915        return snprintf(buf, PAGE_SIZE, "%d\n", chip->tsl2x7x_chip_status);
 916}
 917
 918static ssize_t tsl2x7x_power_state_store(struct device *dev,
 919        struct device_attribute *attr, const char *buf, size_t len)
 920{
 921        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 922        bool value;
 923
 924        if (strtobool(buf, &value))
 925                return -EINVAL;
 926
 927        if (value)
 928                tsl2x7x_chip_on(indio_dev);
 929        else
 930                tsl2x7x_chip_off(indio_dev);
 931
 932        return len;
 933}
 934
 935static ssize_t tsl2x7x_gain_available_show(struct device *dev,
 936        struct device_attribute *attr, char *buf)
 937{
 938        struct tsl2X7X_chip *chip = iio_priv(dev_to_iio_dev(dev));
 939
 940        switch (chip->id) {
 941        case tsl2571:
 942        case tsl2671:
 943        case tmd2671:
 944        case tsl2771:
 945        case tmd2771:
 946                return snprintf(buf, PAGE_SIZE, "%s\n", "1 8 16 128");
 947        }
 948
 949        return snprintf(buf, PAGE_SIZE, "%s\n", "1 8 16 120");
 950}
 951
 952static ssize_t tsl2x7x_prox_gain_available_show(struct device *dev,
 953        struct device_attribute *attr, char *buf)
 954{
 955                return snprintf(buf, PAGE_SIZE, "%s\n", "1 2 4 8");
 956}
 957
 958static ssize_t tsl2x7x_als_time_show(struct device *dev,
 959        struct device_attribute *attr, char *buf)
 960{
 961        struct tsl2X7X_chip *chip = iio_priv(dev_to_iio_dev(dev));
 962        int y, z;
 963
 964        y = (TSL2X7X_MAX_TIMER_CNT - (u8)chip->tsl2x7x_settings.als_time) + 1;
 965        z = y * TSL2X7X_MIN_ITIME;
 966        y /= 1000;
 967        z %= 1000;
 968
 969        return snprintf(buf, PAGE_SIZE, "%d.%03d\n", y, z);
 970}
 971
 972static ssize_t tsl2x7x_als_time_store(struct device *dev,
 973        struct device_attribute *attr, const char *buf, size_t len)
 974{
 975        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 976        struct tsl2X7X_chip *chip = iio_priv(indio_dev);
 977        struct tsl2x7x_parse_result result;
 978        int ret;
 979
 980        ret = iio_str_to_fixpoint(buf, 100, &result.integer, &result.fract);
 981        if (ret)
 982                return ret;
 983
 984        result.fract /= 3;
 985        chip->tsl2x7x_settings.als_time =
 986                        TSL2X7X_MAX_TIMER_CNT - (u8)result.fract;
 987
 988        dev_info(&chip->client->dev, "%s: als time = %d",
 989                __func__, chip->tsl2x7x_settings.als_time);
 990
 991        tsl2x7x_invoke_change(indio_dev);
 992
 993        return IIO_VAL_INT_PLUS_MICRO;
 994}
 995
 996static IIO_CONST_ATTR(in_illuminance0_integration_time_available,
 997                ".00272 - .696");
 998
 999static ssize_t tsl2x7x_als_cal_target_show(struct device *dev,
1000        struct device_attribute *attr, char *buf)
1001{
1002        struct tsl2X7X_chip *chip = iio_priv(dev_to_iio_dev(dev));
1003
1004        return snprintf(buf, PAGE_SIZE, "%d\n",
1005                        chip->tsl2x7x_settings.als_cal_target);
1006}
1007
1008static ssize_t tsl2x7x_als_cal_target_store(struct device *dev,
1009        struct device_attribute *attr, const char *buf, size_t len)
1010{
1011        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
1012        struct tsl2X7X_chip *chip = iio_priv(indio_dev);
1013        unsigned long value;
1014
1015        if (kstrtoul(buf, 0, &value))
1016                return -EINVAL;
1017
1018        if (value)
1019                chip->tsl2x7x_settings.als_cal_target = value;
1020
1021        tsl2x7x_invoke_change(indio_dev);
1022
1023        return len;
1024}
1025
1026/* persistence settings */
1027static ssize_t tsl2x7x_als_persistence_show(struct device *dev,
1028        struct device_attribute *attr, char *buf)
1029{
1030        struct tsl2X7X_chip *chip = iio_priv(dev_to_iio_dev(dev));
1031        int y, z, filter_delay;
1032
1033        /* Determine integration time */
1034        y = (TSL2X7X_MAX_TIMER_CNT - (u8)chip->tsl2x7x_settings.als_time) + 1;
1035        z = y * TSL2X7X_MIN_ITIME;
1036        filter_delay = z * (chip->tsl2x7x_settings.persistence & 0x0F);
1037        y = filter_delay / 1000;
1038        z = filter_delay % 1000;
1039
1040        return snprintf(buf, PAGE_SIZE, "%d.%03d\n", y, z);
1041}
1042
1043static ssize_t tsl2x7x_als_persistence_store(struct device *dev,
1044        struct device_attribute *attr, const char *buf, size_t len)
1045{
1046        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
1047        struct tsl2X7X_chip *chip = iio_priv(indio_dev);
1048        struct tsl2x7x_parse_result result;
1049        int y, z, filter_delay;
1050        int ret;
1051
1052        ret = iio_str_to_fixpoint(buf, 100, &result.integer, &result.fract);
1053        if (ret)
1054                return ret;
1055
1056        y = (TSL2X7X_MAX_TIMER_CNT - (u8)chip->tsl2x7x_settings.als_time) + 1;
1057        z = y * TSL2X7X_MIN_ITIME;
1058
1059        filter_delay =
1060                DIV_ROUND_UP((result.integer * 1000) + result.fract, z);
1061
1062        chip->tsl2x7x_settings.persistence &= 0xF0;
1063        chip->tsl2x7x_settings.persistence |= (filter_delay & 0x0F);
1064
1065        dev_info(&chip->client->dev, "%s: als persistence = %d",
1066                __func__, filter_delay);
1067
1068        tsl2x7x_invoke_change(indio_dev);
1069
1070        return IIO_VAL_INT_PLUS_MICRO;
1071}
1072
1073static ssize_t tsl2x7x_prox_persistence_show(struct device *dev,
1074        struct device_attribute *attr, char *buf)
1075{
1076        struct tsl2X7X_chip *chip = iio_priv(dev_to_iio_dev(dev));
1077        int y, z, filter_delay;
1078
1079        /* Determine integration time */
1080        y = (TSL2X7X_MAX_TIMER_CNT - (u8)chip->tsl2x7x_settings.prx_time) + 1;
1081        z = y * TSL2X7X_MIN_ITIME;
1082        filter_delay = z * ((chip->tsl2x7x_settings.persistence & 0xF0) >> 4);
1083        y = filter_delay / 1000;
1084        z = filter_delay % 1000;
1085
1086        return snprintf(buf, PAGE_SIZE, "%d.%03d\n", y, z);
1087}
1088
1089static ssize_t tsl2x7x_prox_persistence_store(struct device *dev,
1090        struct device_attribute *attr, const char *buf, size_t len)
1091{
1092        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
1093        struct tsl2X7X_chip *chip = iio_priv(indio_dev);
1094        struct tsl2x7x_parse_result result;
1095        int y, z, filter_delay;
1096        int ret;
1097
1098        ret = iio_str_to_fixpoint(buf, 100, &result.integer, &result.fract);
1099        if (ret)
1100                return ret;
1101
1102        y = (TSL2X7X_MAX_TIMER_CNT - (u8)chip->tsl2x7x_settings.prx_time) + 1;
1103        z = y * TSL2X7X_MIN_ITIME;
1104
1105        filter_delay =
1106                DIV_ROUND_UP((result.integer * 1000) + result.fract, z);
1107
1108        chip->tsl2x7x_settings.persistence &= 0x0F;
1109        chip->tsl2x7x_settings.persistence |= ((filter_delay << 4) & 0xF0);
1110
1111        dev_info(&chip->client->dev, "%s: prox persistence = %d",
1112                __func__, filter_delay);
1113
1114        tsl2x7x_invoke_change(indio_dev);
1115
1116        return IIO_VAL_INT_PLUS_MICRO;
1117}
1118
1119static ssize_t tsl2x7x_do_calibrate(struct device *dev,
1120        struct device_attribute *attr, const char *buf, size_t len)
1121{
1122        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
1123        bool value;
1124
1125        if (strtobool(buf, &value))
1126                return -EINVAL;
1127
1128        if (value)
1129                tsl2x7x_als_calibrate(indio_dev);
1130
1131        tsl2x7x_invoke_change(indio_dev);
1132
1133        return len;
1134}
1135
1136static ssize_t tsl2x7x_luxtable_show(struct device *dev,
1137        struct device_attribute *attr, char *buf)
1138{
1139        struct tsl2X7X_chip *chip = iio_priv(dev_to_iio_dev(dev));
1140        int i = 0;
1141        int offset = 0;
1142
1143        while (i < (TSL2X7X_MAX_LUX_TABLE_SIZE * 3)) {
1144                offset += snprintf(buf + offset, PAGE_SIZE, "%u,%u,%u,",
1145                        chip->tsl2x7x_device_lux[i].ratio,
1146                        chip->tsl2x7x_device_lux[i].ch0,
1147                        chip->tsl2x7x_device_lux[i].ch1);
1148                if (chip->tsl2x7x_device_lux[i].ratio == 0) {
1149                        /* We just printed the first "0" entry.
1150                         * Now get rid of the extra "," and break. */
1151                        offset--;
1152                        break;
1153                }
1154                i++;
1155        }
1156
1157        offset += snprintf(buf + offset, PAGE_SIZE, "\n");
1158        return offset;
1159}
1160
1161static ssize_t tsl2x7x_luxtable_store(struct device *dev,
1162        struct device_attribute *attr, const char *buf, size_t len)
1163{
1164        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
1165        struct tsl2X7X_chip *chip = iio_priv(indio_dev);
1166        int value[ARRAY_SIZE(chip->tsl2x7x_device_lux)*3 + 1];
1167        int n;
1168
1169        get_options(buf, ARRAY_SIZE(value), value);
1170
1171        /* We now have an array of ints starting at value[1], and
1172         * enumerated by value[0].
1173         * We expect each group of three ints is one table entry,
1174         * and the last table entry is all 0.
1175         */
1176        n = value[0];
1177        if ((n % 3) || n < 6 ||
1178                        n > ((ARRAY_SIZE(chip->tsl2x7x_device_lux) - 1) * 3)) {
1179                dev_info(dev, "LUX TABLE INPUT ERROR 1 Value[0]=%d\n", n);
1180                return -EINVAL;
1181        }
1182
1183        if ((value[(n - 2)] | value[(n - 1)] | value[n]) != 0) {
1184                dev_info(dev, "LUX TABLE INPUT ERROR 2 Value[0]=%d\n", n);
1185                return -EINVAL;
1186        }
1187
1188        if (chip->tsl2x7x_chip_status == TSL2X7X_CHIP_WORKING)
1189                tsl2x7x_chip_off(indio_dev);
1190
1191        /* Zero out the table */
1192        memset(chip->tsl2x7x_device_lux, 0, sizeof(chip->tsl2x7x_device_lux));
1193        memcpy(chip->tsl2x7x_device_lux, &value[1], (value[0] * 4));
1194
1195        tsl2x7x_invoke_change(indio_dev);
1196
1197        return len;
1198}
1199
1200static ssize_t tsl2x7x_do_prox_calibrate(struct device *dev,
1201        struct device_attribute *attr, const char *buf, size_t len)
1202{
1203        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
1204        bool value;
1205
1206        if (strtobool(buf, &value))
1207                return -EINVAL;
1208
1209        if (value)
1210                tsl2x7x_prox_cal(indio_dev);
1211
1212        tsl2x7x_invoke_change(indio_dev);
1213
1214        return len;
1215}
1216
1217static int tsl2x7x_read_interrupt_config(struct iio_dev *indio_dev,
1218                                         const struct iio_chan_spec *chan,
1219                                         enum iio_event_type type,
1220                                         enum iio_event_direction dir)
1221{
1222        struct tsl2X7X_chip *chip = iio_priv(indio_dev);
1223        int ret;
1224
1225        if (chan->type == IIO_INTENSITY)
1226                ret = !!(chip->tsl2x7x_settings.interrupts_en & 0x10);
1227        else
1228                ret = !!(chip->tsl2x7x_settings.interrupts_en & 0x20);
1229
1230        return ret;
1231}
1232
1233static int tsl2x7x_write_interrupt_config(struct iio_dev *indio_dev,
1234                                          const struct iio_chan_spec *chan,
1235                                          enum iio_event_type type,
1236                                          enum iio_event_direction dir,
1237                                          int val)
1238{
1239        struct tsl2X7X_chip *chip = iio_priv(indio_dev);
1240
1241        if (chan->type == IIO_INTENSITY) {
1242                if (val)
1243                        chip->tsl2x7x_settings.interrupts_en |= 0x10;
1244                else
1245                        chip->tsl2x7x_settings.interrupts_en &= 0x20;
1246        } else {
1247                if (val)
1248                        chip->tsl2x7x_settings.interrupts_en |= 0x20;
1249                else
1250                        chip->tsl2x7x_settings.interrupts_en &= 0x10;
1251        }
1252
1253        tsl2x7x_invoke_change(indio_dev);
1254
1255        return 0;
1256}
1257
1258static int tsl2x7x_write_thresh(struct iio_dev *indio_dev,
1259                                const struct iio_chan_spec *chan,
1260                                enum iio_event_type type,
1261                                enum iio_event_direction dir,
1262                                enum iio_event_info info,
1263                                int val, int val2)
1264{
1265        struct tsl2X7X_chip *chip = iio_priv(indio_dev);
1266
1267        if (chan->type == IIO_INTENSITY) {
1268                switch (dir) {
1269                case IIO_EV_DIR_RISING:
1270                        chip->tsl2x7x_settings.als_thresh_high = val;
1271                        break;
1272                case IIO_EV_DIR_FALLING:
1273                        chip->tsl2x7x_settings.als_thresh_low = val;
1274                        break;
1275                default:
1276                        return -EINVAL;
1277                }
1278        } else {
1279                switch (dir) {
1280                case IIO_EV_DIR_RISING:
1281                        chip->tsl2x7x_settings.prox_thres_high = val;
1282                        break;
1283                case IIO_EV_DIR_FALLING:
1284                        chip->tsl2x7x_settings.prox_thres_low = val;
1285                        break;
1286                default:
1287                        return -EINVAL;
1288                }
1289        }
1290
1291        tsl2x7x_invoke_change(indio_dev);
1292
1293        return 0;
1294}
1295
1296static int tsl2x7x_read_thresh(struct iio_dev *indio_dev,
1297                               const struct iio_chan_spec *chan,
1298                               enum iio_event_type type,
1299                               enum iio_event_direction dir,
1300                                   enum iio_event_info info,
1301                               int *val, int *val2)
1302{
1303        struct tsl2X7X_chip *chip = iio_priv(indio_dev);
1304
1305        if (chan->type == IIO_INTENSITY) {
1306                switch (dir) {
1307                case IIO_EV_DIR_RISING:
1308                        *val = chip->tsl2x7x_settings.als_thresh_high;
1309                        break;
1310                case IIO_EV_DIR_FALLING:
1311                        *val = chip->tsl2x7x_settings.als_thresh_low;
1312                        break;
1313                default:
1314                        return -EINVAL;
1315                }
1316        } else {
1317                switch (dir) {
1318                case IIO_EV_DIR_RISING:
1319                        *val = chip->tsl2x7x_settings.prox_thres_high;
1320                        break;
1321                case IIO_EV_DIR_FALLING:
1322                        *val = chip->tsl2x7x_settings.prox_thres_low;
1323                        break;
1324                default:
1325                        return -EINVAL;
1326                }
1327        }
1328
1329        return IIO_VAL_INT;
1330}
1331
1332static int tsl2x7x_read_raw(struct iio_dev *indio_dev,
1333                            struct iio_chan_spec const *chan,
1334                            int *val,
1335                            int *val2,
1336                            long mask)
1337{
1338        int ret = -EINVAL;
1339        struct tsl2X7X_chip *chip = iio_priv(indio_dev);
1340
1341        switch (mask) {
1342        case IIO_CHAN_INFO_PROCESSED:
1343                switch (chan->type) {
1344                case IIO_LIGHT:
1345                        tsl2x7x_get_lux(indio_dev);
1346                        *val = chip->als_cur_info.lux;
1347                        ret = IIO_VAL_INT;
1348                        break;
1349                default:
1350                        return -EINVAL;
1351                }
1352                break;
1353        case IIO_CHAN_INFO_RAW:
1354                switch (chan->type) {
1355                case IIO_INTENSITY:
1356                        tsl2x7x_get_lux(indio_dev);
1357                        if (chan->channel == 0)
1358                                *val = chip->als_cur_info.als_ch0;
1359                        else
1360                                *val = chip->als_cur_info.als_ch1;
1361                        ret = IIO_VAL_INT;
1362                        break;
1363                case IIO_PROXIMITY:
1364                        tsl2x7x_get_prox(indio_dev);
1365                        *val = chip->prox_data;
1366                        ret = IIO_VAL_INT;
1367                        break;
1368                default:
1369                        return -EINVAL;
1370                }
1371                break;
1372        case IIO_CHAN_INFO_CALIBSCALE:
1373                if (chan->type == IIO_LIGHT)
1374                        *val =
1375                        tsl2X7X_als_gainadj[chip->tsl2x7x_settings.als_gain];
1376                else
1377                        *val =
1378                        tsl2X7X_prx_gainadj[chip->tsl2x7x_settings.prox_gain];
1379                ret = IIO_VAL_INT;
1380                break;
1381        case IIO_CHAN_INFO_CALIBBIAS:
1382                *val = chip->tsl2x7x_settings.als_gain_trim;
1383                ret = IIO_VAL_INT;
1384                break;
1385
1386        default:
1387                ret = -EINVAL;
1388        }
1389
1390        return ret;
1391}
1392
1393static int tsl2x7x_write_raw(struct iio_dev *indio_dev,
1394                               struct iio_chan_spec const *chan,
1395                               int val,
1396                               int val2,
1397                               long mask)
1398{
1399        struct tsl2X7X_chip *chip = iio_priv(indio_dev);
1400
1401        switch (mask) {
1402        case IIO_CHAN_INFO_CALIBSCALE:
1403                if (chan->type == IIO_INTENSITY) {
1404                        switch (val) {
1405                        case 1:
1406                                chip->tsl2x7x_settings.als_gain = 0;
1407                                break;
1408                        case 8:
1409                                chip->tsl2x7x_settings.als_gain = 1;
1410                                break;
1411                        case 16:
1412                                chip->tsl2x7x_settings.als_gain = 2;
1413                                break;
1414                        case 120:
1415                                switch (chip->id) {
1416                                case tsl2572:
1417                                case tsl2672:
1418                                case tmd2672:
1419                                case tsl2772:
1420                                case tmd2772:
1421                                        return -EINVAL;
1422                                }
1423                                chip->tsl2x7x_settings.als_gain = 3;
1424                                break;
1425                        case 128:
1426                                switch (chip->id) {
1427                                case tsl2571:
1428                                case tsl2671:
1429                                case tmd2671:
1430                                case tsl2771:
1431                                case tmd2771:
1432                                        return -EINVAL;
1433                                }
1434                                chip->tsl2x7x_settings.als_gain = 3;
1435                                break;
1436                        default:
1437                                return -EINVAL;
1438                        }
1439                } else {
1440                        switch (val) {
1441                        case 1:
1442                                chip->tsl2x7x_settings.prox_gain = 0;
1443                                break;
1444                        case 2:
1445                                chip->tsl2x7x_settings.prox_gain = 1;
1446                                break;
1447                        case 4:
1448                                chip->tsl2x7x_settings.prox_gain = 2;
1449                                break;
1450                        case 8:
1451                                chip->tsl2x7x_settings.prox_gain = 3;
1452                                break;
1453                        default:
1454                                return -EINVAL;
1455                        }
1456                }
1457                break;
1458        case IIO_CHAN_INFO_CALIBBIAS:
1459                chip->tsl2x7x_settings.als_gain_trim = val;
1460                break;
1461
1462        default:
1463                return -EINVAL;
1464        }
1465
1466        tsl2x7x_invoke_change(indio_dev);
1467
1468        return 0;
1469}
1470
1471static DEVICE_ATTR(power_state, S_IRUGO | S_IWUSR,
1472                tsl2x7x_power_state_show, tsl2x7x_power_state_store);
1473
1474static DEVICE_ATTR(in_proximity0_calibscale_available, S_IRUGO,
1475                tsl2x7x_prox_gain_available_show, NULL);
1476
1477static DEVICE_ATTR(in_illuminance0_calibscale_available, S_IRUGO,
1478                tsl2x7x_gain_available_show, NULL);
1479
1480static DEVICE_ATTR(in_illuminance0_integration_time, S_IRUGO | S_IWUSR,
1481                tsl2x7x_als_time_show, tsl2x7x_als_time_store);
1482
1483static DEVICE_ATTR(in_illuminance0_target_input, S_IRUGO | S_IWUSR,
1484                tsl2x7x_als_cal_target_show, tsl2x7x_als_cal_target_store);
1485
1486static DEVICE_ATTR(in_illuminance0_calibrate, S_IWUSR, NULL,
1487                tsl2x7x_do_calibrate);
1488
1489static DEVICE_ATTR(in_proximity0_calibrate, S_IWUSR, NULL,
1490                tsl2x7x_do_prox_calibrate);
1491
1492static DEVICE_ATTR(in_illuminance0_lux_table, S_IRUGO | S_IWUSR,
1493                tsl2x7x_luxtable_show, tsl2x7x_luxtable_store);
1494
1495static DEVICE_ATTR(in_intensity0_thresh_period, S_IRUGO | S_IWUSR,
1496                tsl2x7x_als_persistence_show, tsl2x7x_als_persistence_store);
1497
1498static DEVICE_ATTR(in_proximity0_thresh_period, S_IRUGO | S_IWUSR,
1499                tsl2x7x_prox_persistence_show, tsl2x7x_prox_persistence_store);
1500
1501/* Use the default register values to identify the Taos device */
1502static int tsl2x7x_device_id(unsigned char *id, int target)
1503{
1504        switch (target) {
1505        case tsl2571:
1506        case tsl2671:
1507        case tsl2771:
1508                return (*id & 0xf0) == TRITON_ID;
1509        case tmd2671:
1510        case tmd2771:
1511                return (*id & 0xf0) == HALIBUT_ID;
1512        case tsl2572:
1513        case tsl2672:
1514        case tmd2672:
1515        case tsl2772:
1516        case tmd2772:
1517                return (*id & 0xf0) == SWORDFISH_ID;
1518        }
1519
1520        return -EINVAL;
1521}
1522
1523static irqreturn_t tsl2x7x_event_handler(int irq, void *private)
1524{
1525        struct iio_dev *indio_dev = private;
1526        struct tsl2X7X_chip *chip = iio_priv(indio_dev);
1527        s64 timestamp = iio_get_time_ns();
1528        int ret;
1529        u8 value;
1530
1531        value = i2c_smbus_read_byte_data(chip->client,
1532                TSL2X7X_CMD_REG | TSL2X7X_STATUS);
1533
1534        /* What type of interrupt do we need to process */
1535        if (value & TSL2X7X_STA_PRX_INTR) {
1536                tsl2x7x_get_prox(indio_dev); /* freshen data for ABI */
1537                iio_push_event(indio_dev,
1538                               IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY,
1539                                                    0,
1540                                                    IIO_EV_TYPE_THRESH,
1541                                                    IIO_EV_DIR_EITHER),
1542                                                    timestamp);
1543        }
1544
1545        if (value & TSL2X7X_STA_ALS_INTR) {
1546                tsl2x7x_get_lux(indio_dev); /* freshen data for ABI */
1547                iio_push_event(indio_dev,
1548                       IIO_UNMOD_EVENT_CODE(IIO_LIGHT,
1549                                            0,
1550                                            IIO_EV_TYPE_THRESH,
1551                                            IIO_EV_DIR_EITHER),
1552                                            timestamp);
1553        }
1554        /* Clear interrupt now that we have handled it. */
1555        ret = i2c_smbus_write_byte(chip->client,
1556                TSL2X7X_CMD_REG | TSL2X7X_CMD_SPL_FN |
1557                TSL2X7X_CMD_PROXALS_INT_CLR);
1558        if (ret < 0)
1559                dev_err(&chip->client->dev,
1560                        "Failed to clear irq from event handler. err = %d\n",
1561                        ret);
1562
1563        return IRQ_HANDLED;
1564}
1565
1566static struct attribute *tsl2x7x_ALS_device_attrs[] = {
1567        &dev_attr_power_state.attr,
1568        &dev_attr_in_illuminance0_calibscale_available.attr,
1569        &dev_attr_in_illuminance0_integration_time.attr,
1570        &iio_const_attr_in_illuminance0_integration_time_available.dev_attr.attr,
1571        &dev_attr_in_illuminance0_target_input.attr,
1572        &dev_attr_in_illuminance0_calibrate.attr,
1573        &dev_attr_in_illuminance0_lux_table.attr,
1574        NULL
1575};
1576
1577static struct attribute *tsl2x7x_PRX_device_attrs[] = {
1578        &dev_attr_power_state.attr,
1579        &dev_attr_in_proximity0_calibrate.attr,
1580        NULL
1581};
1582
1583static struct attribute *tsl2x7x_ALSPRX_device_attrs[] = {
1584        &dev_attr_power_state.attr,
1585        &dev_attr_in_illuminance0_calibscale_available.attr,
1586        &dev_attr_in_illuminance0_integration_time.attr,
1587        &iio_const_attr_in_illuminance0_integration_time_available.dev_attr.attr,
1588        &dev_attr_in_illuminance0_target_input.attr,
1589        &dev_attr_in_illuminance0_calibrate.attr,
1590        &dev_attr_in_illuminance0_lux_table.attr,
1591        &dev_attr_in_proximity0_calibrate.attr,
1592        NULL
1593};
1594
1595static struct attribute *tsl2x7x_PRX2_device_attrs[] = {
1596        &dev_attr_power_state.attr,
1597        &dev_attr_in_proximity0_calibrate.attr,
1598        &dev_attr_in_proximity0_calibscale_available.attr,
1599        NULL
1600};
1601
1602static struct attribute *tsl2x7x_ALSPRX2_device_attrs[] = {
1603        &dev_attr_power_state.attr,
1604        &dev_attr_in_illuminance0_calibscale_available.attr,
1605        &dev_attr_in_illuminance0_integration_time.attr,
1606        &iio_const_attr_in_illuminance0_integration_time_available.dev_attr.attr,
1607        &dev_attr_in_illuminance0_target_input.attr,
1608        &dev_attr_in_illuminance0_calibrate.attr,
1609        &dev_attr_in_illuminance0_lux_table.attr,
1610        &dev_attr_in_proximity0_calibrate.attr,
1611        &dev_attr_in_proximity0_calibscale_available.attr,
1612        NULL
1613};
1614
1615static struct attribute *tsl2X7X_ALS_event_attrs[] = {
1616        &dev_attr_in_intensity0_thresh_period.attr,
1617        NULL,
1618};
1619static struct attribute *tsl2X7X_PRX_event_attrs[] = {
1620        &dev_attr_in_proximity0_thresh_period.attr,
1621        NULL,
1622};
1623
1624static struct attribute *tsl2X7X_ALSPRX_event_attrs[] = {
1625        &dev_attr_in_intensity0_thresh_period.attr,
1626        &dev_attr_in_proximity0_thresh_period.attr,
1627        NULL,
1628};
1629
1630static const struct attribute_group tsl2X7X_device_attr_group_tbl[] = {
1631        [ALS] = {
1632                .attrs = tsl2x7x_ALS_device_attrs,
1633        },
1634        [PRX] = {
1635                .attrs = tsl2x7x_PRX_device_attrs,
1636        },
1637        [ALSPRX] = {
1638                .attrs = tsl2x7x_ALSPRX_device_attrs,
1639        },
1640        [PRX2] = {
1641                .attrs = tsl2x7x_PRX2_device_attrs,
1642        },
1643        [ALSPRX2] = {
1644                .attrs = tsl2x7x_ALSPRX2_device_attrs,
1645        },
1646};
1647
1648static struct attribute_group tsl2X7X_event_attr_group_tbl[] = {
1649        [ALS] = {
1650                .attrs = tsl2X7X_ALS_event_attrs,
1651                .name = "events",
1652        },
1653        [PRX] = {
1654                .attrs = tsl2X7X_PRX_event_attrs,
1655                .name = "events",
1656        },
1657        [ALSPRX] = {
1658                .attrs = tsl2X7X_ALSPRX_event_attrs,
1659                .name = "events",
1660        },
1661};
1662
1663static const struct iio_info tsl2X7X_device_info[] = {
1664        [ALS] = {
1665                .attrs = &tsl2X7X_device_attr_group_tbl[ALS],
1666                .event_attrs = &tsl2X7X_event_attr_group_tbl[ALS],
1667                .driver_module = THIS_MODULE,
1668                .read_raw = &tsl2x7x_read_raw,
1669                .write_raw = &tsl2x7x_write_raw,
1670                .read_event_value = &tsl2x7x_read_thresh,
1671                .write_event_value = &tsl2x7x_write_thresh,
1672                .read_event_config = &tsl2x7x_read_interrupt_config,
1673                .write_event_config = &tsl2x7x_write_interrupt_config,
1674        },
1675        [PRX] = {
1676                .attrs = &tsl2X7X_device_attr_group_tbl[PRX],
1677                .event_attrs = &tsl2X7X_event_attr_group_tbl[PRX],
1678                .driver_module = THIS_MODULE,
1679                .read_raw = &tsl2x7x_read_raw,
1680                .write_raw = &tsl2x7x_write_raw,
1681                .read_event_value = &tsl2x7x_read_thresh,
1682                .write_event_value = &tsl2x7x_write_thresh,
1683                .read_event_config = &tsl2x7x_read_interrupt_config,
1684                .write_event_config = &tsl2x7x_write_interrupt_config,
1685        },
1686        [ALSPRX] = {
1687                .attrs = &tsl2X7X_device_attr_group_tbl[ALSPRX],
1688                .event_attrs = &tsl2X7X_event_attr_group_tbl[ALSPRX],
1689                .driver_module = THIS_MODULE,
1690                .read_raw = &tsl2x7x_read_raw,
1691                .write_raw = &tsl2x7x_write_raw,
1692                .read_event_value = &tsl2x7x_read_thresh,
1693                .write_event_value = &tsl2x7x_write_thresh,
1694                .read_event_config = &tsl2x7x_read_interrupt_config,
1695                .write_event_config = &tsl2x7x_write_interrupt_config,
1696        },
1697        [PRX2] = {
1698                .attrs = &tsl2X7X_device_attr_group_tbl[PRX2],
1699                .event_attrs = &tsl2X7X_event_attr_group_tbl[PRX],
1700                .driver_module = THIS_MODULE,
1701                .read_raw = &tsl2x7x_read_raw,
1702                .write_raw = &tsl2x7x_write_raw,
1703                .read_event_value = &tsl2x7x_read_thresh,
1704                .write_event_value = &tsl2x7x_write_thresh,
1705                .read_event_config = &tsl2x7x_read_interrupt_config,
1706                .write_event_config = &tsl2x7x_write_interrupt_config,
1707        },
1708        [ALSPRX2] = {
1709                .attrs = &tsl2X7X_device_attr_group_tbl[ALSPRX2],
1710                .event_attrs = &tsl2X7X_event_attr_group_tbl[ALSPRX],
1711                .driver_module = THIS_MODULE,
1712                .read_raw = &tsl2x7x_read_raw,
1713                .write_raw = &tsl2x7x_write_raw,
1714                .read_event_value = &tsl2x7x_read_thresh,
1715                .write_event_value = &tsl2x7x_write_thresh,
1716                .read_event_config = &tsl2x7x_read_interrupt_config,
1717                .write_event_config = &tsl2x7x_write_interrupt_config,
1718        },
1719};
1720
1721static const struct iio_event_spec tsl2x7x_events[] = {
1722        {
1723                .type = IIO_EV_TYPE_THRESH,
1724                .dir = IIO_EV_DIR_RISING,
1725                .mask_separate = BIT(IIO_EV_INFO_VALUE) |
1726                        BIT(IIO_EV_INFO_ENABLE),
1727        }, {
1728                .type = IIO_EV_TYPE_THRESH,
1729                .dir = IIO_EV_DIR_FALLING,
1730                .mask_separate = BIT(IIO_EV_INFO_VALUE) |
1731                        BIT(IIO_EV_INFO_ENABLE),
1732        },
1733};
1734
1735static const struct tsl2x7x_chip_info tsl2x7x_chip_info_tbl[] = {
1736        [ALS] = {
1737                .channel = {
1738                        {
1739                        .type = IIO_LIGHT,
1740                        .indexed = 1,
1741                        .channel = 0,
1742                        .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
1743                        }, {
1744                        .type = IIO_INTENSITY,
1745                        .indexed = 1,
1746                        .channel = 0,
1747                        .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
1748                                BIT(IIO_CHAN_INFO_CALIBSCALE) |
1749                                BIT(IIO_CHAN_INFO_CALIBBIAS),
1750                        .event_spec = tsl2x7x_events,
1751                        .num_event_specs = ARRAY_SIZE(tsl2x7x_events),
1752                        }, {
1753                        .type = IIO_INTENSITY,
1754                        .indexed = 1,
1755                        .channel = 1,
1756                        },
1757                },
1758        .chan_table_elements = 3,
1759        .info = &tsl2X7X_device_info[ALS],
1760        },
1761        [PRX] = {
1762                .channel = {
1763                        {
1764                        .type = IIO_PROXIMITY,
1765                        .indexed = 1,
1766                        .channel = 0,
1767                        .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
1768                        .event_spec = tsl2x7x_events,
1769                        .num_event_specs = ARRAY_SIZE(tsl2x7x_events),
1770                        },
1771                },
1772        .chan_table_elements = 1,
1773        .info = &tsl2X7X_device_info[PRX],
1774        },
1775        [ALSPRX] = {
1776                .channel = {
1777                        {
1778                        .type = IIO_LIGHT,
1779                        .indexed = 1,
1780                        .channel = 0,
1781                        .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED)
1782                        }, {
1783                        .type = IIO_INTENSITY,
1784                        .indexed = 1,
1785                        .channel = 0,
1786                        .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
1787                                BIT(IIO_CHAN_INFO_CALIBSCALE) |
1788                                BIT(IIO_CHAN_INFO_CALIBBIAS),
1789                        .event_spec = tsl2x7x_events,
1790                        .num_event_specs = ARRAY_SIZE(tsl2x7x_events),
1791                        }, {
1792                        .type = IIO_INTENSITY,
1793                        .indexed = 1,
1794                        .channel = 1,
1795                        .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
1796                        }, {
1797                        .type = IIO_PROXIMITY,
1798                        .indexed = 1,
1799                        .channel = 0,
1800                        .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
1801                        .event_spec = tsl2x7x_events,
1802                        .num_event_specs = ARRAY_SIZE(tsl2x7x_events),
1803                        },
1804                },
1805        .chan_table_elements = 4,
1806        .info = &tsl2X7X_device_info[ALSPRX],
1807        },
1808        [PRX2] = {
1809                .channel = {
1810                        {
1811                        .type = IIO_PROXIMITY,
1812                        .indexed = 1,
1813                        .channel = 0,
1814                        .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
1815                                BIT(IIO_CHAN_INFO_CALIBSCALE),
1816                        .event_spec = tsl2x7x_events,
1817                        .num_event_specs = ARRAY_SIZE(tsl2x7x_events),
1818                        },
1819                },
1820        .chan_table_elements = 1,
1821        .info = &tsl2X7X_device_info[PRX2],
1822        },
1823        [ALSPRX2] = {
1824                .channel = {
1825                        {
1826                        .type = IIO_LIGHT,
1827                        .indexed = 1,
1828                        .channel = 0,
1829                        .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
1830                        }, {
1831                        .type = IIO_INTENSITY,
1832                        .indexed = 1,
1833                        .channel = 0,
1834                        .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
1835                                BIT(IIO_CHAN_INFO_CALIBSCALE) |
1836                                BIT(IIO_CHAN_INFO_CALIBBIAS),
1837                        .event_spec = tsl2x7x_events,
1838                        .num_event_specs = ARRAY_SIZE(tsl2x7x_events),
1839                        }, {
1840                        .type = IIO_INTENSITY,
1841                        .indexed = 1,
1842                        .channel = 1,
1843                        .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
1844                        }, {
1845                        .type = IIO_PROXIMITY,
1846                        .indexed = 1,
1847                        .channel = 0,
1848                        .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
1849                                BIT(IIO_CHAN_INFO_CALIBSCALE),
1850                        .event_spec = tsl2x7x_events,
1851                        .num_event_specs = ARRAY_SIZE(tsl2x7x_events),
1852                        },
1853                },
1854        .chan_table_elements = 4,
1855        .info = &tsl2X7X_device_info[ALSPRX2],
1856        },
1857};
1858
1859static int tsl2x7x_probe(struct i2c_client *clientp,
1860        const struct i2c_device_id *id)
1861{
1862        int ret;
1863        unsigned char device_id;
1864        struct iio_dev *indio_dev;
1865        struct tsl2X7X_chip *chip;
1866
1867        indio_dev = devm_iio_device_alloc(&clientp->dev, sizeof(*chip));
1868        if (!indio_dev)
1869                return -ENOMEM;
1870
1871        chip = iio_priv(indio_dev);
1872        chip->client = clientp;
1873        i2c_set_clientdata(clientp, indio_dev);
1874
1875        ret = tsl2x7x_i2c_read(chip->client,
1876                TSL2X7X_CHIPID, &device_id);
1877        if (ret < 0)
1878                return ret;
1879
1880        if ((!tsl2x7x_device_id(&device_id, id->driver_data)) ||
1881                (tsl2x7x_device_id(&device_id, id->driver_data) == -EINVAL)) {
1882                dev_info(&chip->client->dev,
1883                                "%s: i2c device found does not match expected id\n",
1884                                __func__);
1885                return -EINVAL;
1886        }
1887
1888        ret = i2c_smbus_write_byte(clientp, (TSL2X7X_CMD_REG | TSL2X7X_CNTRL));
1889        if (ret < 0) {
1890                dev_err(&clientp->dev, "write to cmd reg failed. err = %d\n",
1891                        ret);
1892                return ret;
1893        }
1894
1895        /* ALS and PROX functions can be invoked via user space poll
1896         * or H/W interrupt. If busy return last sample. */
1897        mutex_init(&chip->als_mutex);
1898        mutex_init(&chip->prox_mutex);
1899
1900        chip->tsl2x7x_chip_status = TSL2X7X_CHIP_UNKNOWN;
1901        chip->pdata = dev_get_platdata(&clientp->dev);
1902        chip->id = id->driver_data;
1903        chip->chip_info =
1904                &tsl2x7x_chip_info_tbl[device_channel_config[id->driver_data]];
1905
1906        indio_dev->info = chip->chip_info->info;
1907        indio_dev->dev.parent = &clientp->dev;
1908        indio_dev->modes = INDIO_DIRECT_MODE;
1909        indio_dev->name = chip->client->name;
1910        indio_dev->channels = chip->chip_info->channel;
1911        indio_dev->num_channels = chip->chip_info->chan_table_elements;
1912
1913        if (clientp->irq) {
1914                ret = devm_request_threaded_irq(&clientp->dev, clientp->irq,
1915                                                NULL,
1916                                                &tsl2x7x_event_handler,
1917                                                IRQF_TRIGGER_RISING |
1918                                                IRQF_ONESHOT,
1919                                                "TSL2X7X_event",
1920                                                indio_dev);
1921                if (ret) {
1922                        dev_err(&clientp->dev,
1923                                "%s: irq request failed", __func__);
1924                        return ret;
1925                }
1926        }
1927
1928        /* Load up the defaults */
1929        tsl2x7x_defaults(chip);
1930        /* Make sure the chip is on */
1931        tsl2x7x_chip_on(indio_dev);
1932
1933        ret = iio_device_register(indio_dev);
1934        if (ret) {
1935                dev_err(&clientp->dev,
1936                        "%s: iio registration failed\n", __func__);
1937                return ret;
1938        }
1939
1940        dev_info(&clientp->dev, "%s Light sensor found.\n", id->name);
1941
1942        return 0;
1943}
1944
1945static int tsl2x7x_suspend(struct device *dev)
1946{
1947        struct iio_dev *indio_dev = dev_get_drvdata(dev);
1948        struct tsl2X7X_chip *chip = iio_priv(indio_dev);
1949        int ret = 0;
1950
1951        if (chip->tsl2x7x_chip_status == TSL2X7X_CHIP_WORKING) {
1952                ret = tsl2x7x_chip_off(indio_dev);
1953                chip->tsl2x7x_chip_status = TSL2X7X_CHIP_SUSPENDED;
1954        }
1955
1956        if (chip->pdata && chip->pdata->platform_power) {
1957                pm_message_t pmm = {PM_EVENT_SUSPEND};
1958
1959                chip->pdata->platform_power(dev, pmm);
1960        }
1961
1962        return ret;
1963}
1964
1965static int tsl2x7x_resume(struct device *dev)
1966{
1967        struct iio_dev *indio_dev = dev_get_drvdata(dev);
1968        struct tsl2X7X_chip *chip = iio_priv(indio_dev);
1969        int ret = 0;
1970
1971        if (chip->pdata && chip->pdata->platform_power) {
1972                pm_message_t pmm = {PM_EVENT_RESUME};
1973
1974                chip->pdata->platform_power(dev, pmm);
1975        }
1976
1977        if (chip->tsl2x7x_chip_status == TSL2X7X_CHIP_SUSPENDED)
1978                ret = tsl2x7x_chip_on(indio_dev);
1979
1980        return ret;
1981}
1982
1983static int tsl2x7x_remove(struct i2c_client *client)
1984{
1985        struct iio_dev *indio_dev = i2c_get_clientdata(client);
1986
1987        tsl2x7x_chip_off(indio_dev);
1988
1989        iio_device_unregister(indio_dev);
1990
1991        return 0;
1992}
1993
1994static struct i2c_device_id tsl2x7x_idtable[] = {
1995        { "tsl2571", tsl2571 },
1996        { "tsl2671", tsl2671 },
1997        { "tmd2671", tmd2671 },
1998        { "tsl2771", tsl2771 },
1999        { "tmd2771", tmd2771 },
2000        { "tsl2572", tsl2572 },
2001        { "tsl2672", tsl2672 },
2002        { "tmd2672", tmd2672 },
2003        { "tsl2772", tsl2772 },
2004        { "tmd2772", tmd2772 },
2005        {}
2006};
2007
2008MODULE_DEVICE_TABLE(i2c, tsl2x7x_idtable);
2009
2010static const struct dev_pm_ops tsl2x7x_pm_ops = {
2011        .suspend = tsl2x7x_suspend,
2012        .resume  = tsl2x7x_resume,
2013};
2014
2015/* Driver definition */
2016static struct i2c_driver tsl2x7x_driver = {
2017        .driver = {
2018                .name = "tsl2x7x",
2019                .pm = &tsl2x7x_pm_ops,
2020        },
2021        .id_table = tsl2x7x_idtable,
2022        .probe = tsl2x7x_probe,
2023        .remove = tsl2x7x_remove,
2024};
2025
2026module_i2c_driver(tsl2x7x_driver);
2027
2028MODULE_AUTHOR("J. August Brenner<jbrenner@taosinc.com>");
2029MODULE_DESCRIPTION("TAOS tsl2x7x ambient and proximity light sensor driver");
2030MODULE_LICENSE("GPL");
2031