linux/drivers/iio/light/pa12203001.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2015 Intel Corporation
   3 *
   4 * Driver for TXC PA12203001 Proximity and Ambient Light Sensor.
   5 *
   6 * This program is free software; you can redistribute it and/or modify it
   7 * under the terms of the GNU General Public License version 2 as published by
   8 * the Free Software Foundation.
   9 * To do: Interrupt support.
  10 */
  11
  12#include <linux/kernel.h>
  13#include <linux/module.h>
  14#include <linux/acpi.h>
  15#include <linux/delay.h>
  16#include <linux/i2c.h>
  17#include <linux/iio/iio.h>
  18#include <linux/iio/sysfs.h>
  19#include <linux/mutex.h>
  20#include <linux/pm.h>
  21#include <linux/pm_runtime.h>
  22#include <linux/regmap.h>
  23
  24#define PA12203001_DRIVER_NAME  "pa12203001"
  25
  26#define PA12203001_REG_CFG0             0x00
  27#define PA12203001_REG_CFG1             0x01
  28#define PA12203001_REG_CFG2             0x02
  29#define PA12203001_REG_CFG3             0x03
  30
  31#define PA12203001_REG_ADL              0x0b
  32#define PA12203001_REG_PDH              0x0e
  33
  34#define PA12203001_REG_POFS             0x10
  35#define PA12203001_REG_PSET             0x11
  36
  37#define PA12203001_ALS_EN_MASK          BIT(0)
  38#define PA12203001_PX_EN_MASK           BIT(1)
  39#define PA12203001_PX_NORMAL_MODE_MASK          GENMASK(7, 6)
  40#define PA12203001_AFSR_MASK            GENMASK(5, 4)
  41#define PA12203001_AFSR_SHIFT           4
  42
  43#define PA12203001_PSCAN                        0x03
  44
  45/* als range 31000, ps, als disabled */
  46#define PA12203001_REG_CFG0_DEFAULT             0x30
  47
  48/* led current: 100 mA */
  49#define PA12203001_REG_CFG1_DEFAULT             0x20
  50
  51/* ps mode: normal, interrupts not active */
  52#define PA12203001_REG_CFG2_DEFAULT             0xcc
  53
  54#define PA12203001_REG_CFG3_DEFAULT             0x00
  55
  56#define PA12203001_SLEEP_DELAY_MS               3000
  57
  58#define PA12203001_CHIP_ENABLE          0xff
  59#define PA12203001_CHIP_DISABLE         0x00
  60
  61/* available scales: corresponding to [500, 4000, 7000, 31000]  lux */
  62static const int pa12203001_scales[] = { 7629, 61036, 106813, 473029};
  63
  64struct pa12203001_data {
  65        struct i2c_client *client;
  66
  67        /* protect device states */
  68        struct mutex lock;
  69
  70        bool als_enabled;
  71        bool px_enabled;
  72        bool als_needs_enable;
  73        bool px_needs_enable;
  74
  75        struct regmap *map;
  76};
  77
  78static const struct {
  79        u8 reg;
  80        u8 val;
  81} regvals[] = {
  82        {PA12203001_REG_CFG0, PA12203001_REG_CFG0_DEFAULT},
  83        {PA12203001_REG_CFG1, PA12203001_REG_CFG1_DEFAULT},
  84        {PA12203001_REG_CFG2, PA12203001_REG_CFG2_DEFAULT},
  85        {PA12203001_REG_CFG3, PA12203001_REG_CFG3_DEFAULT},
  86        {PA12203001_REG_PSET, PA12203001_PSCAN},
  87};
  88
  89static IIO_CONST_ATTR(in_illuminance_scale_available,
  90                      "0.007629 0.061036 0.106813 0.473029");
  91
  92static struct attribute *pa12203001_attrs[] = {
  93        &iio_const_attr_in_illuminance_scale_available.dev_attr.attr,
  94        NULL
  95};
  96
  97static const struct attribute_group pa12203001_attr_group = {
  98        .attrs = pa12203001_attrs,
  99};
 100
 101static const struct iio_chan_spec pa12203001_channels[] = {
 102        {
 103                .type = IIO_LIGHT,
 104                .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
 105                                      BIT(IIO_CHAN_INFO_SCALE),
 106        },
 107        {
 108                .type = IIO_PROXIMITY,
 109                .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
 110        }
 111};
 112
 113static const struct regmap_range pa12203001_volatile_regs_ranges[] = {
 114        regmap_reg_range(PA12203001_REG_ADL, PA12203001_REG_ADL + 1),
 115        regmap_reg_range(PA12203001_REG_PDH, PA12203001_REG_PDH),
 116};
 117
 118static const struct regmap_access_table pa12203001_volatile_regs = {
 119        .yes_ranges = pa12203001_volatile_regs_ranges,
 120        .n_yes_ranges = ARRAY_SIZE(pa12203001_volatile_regs_ranges),
 121};
 122
 123static const struct regmap_config pa12203001_regmap_config = {
 124        .reg_bits = 8,
 125        .val_bits = 8,
 126        .max_register = PA12203001_REG_PSET,
 127        .cache_type = REGCACHE_RBTREE,
 128        .volatile_table = &pa12203001_volatile_regs,
 129};
 130
 131static inline int pa12203001_als_enable(struct pa12203001_data *data, u8 enable)
 132{
 133        int ret;
 134
 135        ret = regmap_update_bits(data->map, PA12203001_REG_CFG0,
 136                                 PA12203001_ALS_EN_MASK, enable);
 137        if (ret < 0)
 138                return ret;
 139
 140        data->als_enabled = !!enable;
 141
 142        return 0;
 143}
 144
 145static inline int pa12203001_px_enable(struct pa12203001_data *data, u8 enable)
 146{
 147        int ret;
 148
 149        ret = regmap_update_bits(data->map, PA12203001_REG_CFG0,
 150                                 PA12203001_PX_EN_MASK, enable);
 151        if (ret < 0)
 152                return ret;
 153
 154        data->px_enabled = !!enable;
 155
 156        return 0;
 157}
 158
 159static int pa12203001_set_power_state(struct pa12203001_data *data, bool on,
 160                                      u8 mask)
 161{
 162#ifdef CONFIG_PM
 163        int ret;
 164
 165        if (on && (mask & PA12203001_ALS_EN_MASK)) {
 166                mutex_lock(&data->lock);
 167                if (data->px_enabled) {
 168                        ret = pa12203001_als_enable(data,
 169                                                    PA12203001_ALS_EN_MASK);
 170                        if (ret < 0)
 171                                goto err;
 172                } else {
 173                        data->als_needs_enable = true;
 174                }
 175                mutex_unlock(&data->lock);
 176        }
 177
 178        if (on && (mask & PA12203001_PX_EN_MASK)) {
 179                mutex_lock(&data->lock);
 180                if (data->als_enabled) {
 181                        ret = pa12203001_px_enable(data, PA12203001_PX_EN_MASK);
 182                        if (ret < 0)
 183                                goto err;
 184                } else {
 185                        data->px_needs_enable = true;
 186                }
 187                mutex_unlock(&data->lock);
 188        }
 189
 190        if (on) {
 191                ret = pm_runtime_get_sync(&data->client->dev);
 192                if (ret < 0)
 193                        pm_runtime_put_noidle(&data->client->dev);
 194
 195        } else {
 196                pm_runtime_mark_last_busy(&data->client->dev);
 197                ret = pm_runtime_put_autosuspend(&data->client->dev);
 198        }
 199
 200        return ret;
 201
 202err:
 203        mutex_unlock(&data->lock);
 204        return ret;
 205
 206#endif
 207        return 0;
 208}
 209
 210static int pa12203001_read_raw(struct iio_dev *indio_dev,
 211                               struct iio_chan_spec const *chan, int *val,
 212                               int *val2, long mask)
 213{
 214        struct pa12203001_data *data = iio_priv(indio_dev);
 215        int ret;
 216        u8 dev_mask;
 217        unsigned int reg_byte;
 218        __le16 reg_word;
 219
 220        switch (mask) {
 221        case IIO_CHAN_INFO_RAW:
 222                switch (chan->type) {
 223                case IIO_LIGHT:
 224                        dev_mask = PA12203001_ALS_EN_MASK;
 225                        ret = pa12203001_set_power_state(data, true, dev_mask);
 226                        if (ret < 0)
 227                                return ret;
 228                        /*
 229                         * ALS ADC value is stored in registers
 230                         * PA12203001_REG_ADL and in PA12203001_REG_ADL + 1.
 231                         */
 232                        ret = regmap_bulk_read(data->map, PA12203001_REG_ADL,
 233                                               &reg_word, 2);
 234                        if (ret < 0)
 235                                goto reg_err;
 236
 237                        *val = le16_to_cpu(reg_word);
 238                        ret = pa12203001_set_power_state(data, false, dev_mask);
 239                        if (ret < 0)
 240                                return ret;
 241                        break;
 242                case IIO_PROXIMITY:
 243                        dev_mask = PA12203001_PX_EN_MASK;
 244                        ret = pa12203001_set_power_state(data, true, dev_mask);
 245                        if (ret < 0)
 246                                return ret;
 247                        ret = regmap_read(data->map, PA12203001_REG_PDH,
 248                                          &reg_byte);
 249                        if (ret < 0)
 250                                goto reg_err;
 251
 252                        *val = reg_byte;
 253                        ret = pa12203001_set_power_state(data, false, dev_mask);
 254                        if (ret < 0)
 255                                return ret;
 256                        break;
 257                default:
 258                        return -EINVAL;
 259                }
 260                return IIO_VAL_INT;
 261        case IIO_CHAN_INFO_SCALE:
 262                ret = regmap_read(data->map, PA12203001_REG_CFG0, &reg_byte);
 263                if (ret < 0)
 264                        return ret;
 265                *val = 0;
 266                reg_byte = (reg_byte & PA12203001_AFSR_MASK);
 267                *val2 = pa12203001_scales[reg_byte >> 4];
 268                return IIO_VAL_INT_PLUS_MICRO;
 269        default:
 270                return -EINVAL;
 271        }
 272
 273reg_err:
 274        pa12203001_set_power_state(data, false, dev_mask);
 275        return ret;
 276}
 277
 278static int pa12203001_write_raw(struct iio_dev *indio_dev,
 279                                struct iio_chan_spec const *chan, int val,
 280                                int val2, long mask)
 281{
 282        struct pa12203001_data *data = iio_priv(indio_dev);
 283        int i, ret, new_val;
 284        unsigned int reg_byte;
 285
 286        switch (mask) {
 287        case IIO_CHAN_INFO_SCALE:
 288                ret = regmap_read(data->map, PA12203001_REG_CFG0, &reg_byte);
 289                if (val != 0 || ret < 0)
 290                        return -EINVAL;
 291                for (i = 0; i < ARRAY_SIZE(pa12203001_scales); i++) {
 292                        if (val2 == pa12203001_scales[i]) {
 293                                new_val = i << PA12203001_AFSR_SHIFT;
 294                                return regmap_update_bits(data->map,
 295                                                          PA12203001_REG_CFG0,
 296                                                          PA12203001_AFSR_MASK,
 297                                                          new_val);
 298                        }
 299                }
 300                break;
 301        default:
 302                break;
 303        }
 304
 305        return -EINVAL;
 306}
 307
 308static const struct iio_info pa12203001_info = {
 309        .driver_module  = THIS_MODULE,
 310        .read_raw = pa12203001_read_raw,
 311        .write_raw = pa12203001_write_raw,
 312        .attrs = &pa12203001_attr_group,
 313};
 314
 315static int pa12203001_init(struct iio_dev *indio_dev)
 316{
 317        struct pa12203001_data *data = iio_priv(indio_dev);
 318        int i, ret;
 319
 320        for (i = 0; i < ARRAY_SIZE(regvals); i++) {
 321                ret = regmap_write(data->map, regvals[i].reg, regvals[i].val);
 322                if (ret < 0)
 323                        return ret;
 324        }
 325
 326        return 0;
 327}
 328
 329static int pa12203001_power_chip(struct iio_dev *indio_dev, u8 state)
 330{
 331        struct pa12203001_data *data = iio_priv(indio_dev);
 332        int ret;
 333
 334        mutex_lock(&data->lock);
 335        ret = pa12203001_als_enable(data, state);
 336        if (ret < 0)
 337                goto out;
 338
 339        ret = pa12203001_px_enable(data, state);
 340
 341out:
 342        mutex_unlock(&data->lock);
 343        return ret;
 344}
 345
 346static int pa12203001_probe(struct i2c_client *client,
 347                            const struct i2c_device_id *id)
 348{
 349        struct pa12203001_data *data;
 350        struct iio_dev *indio_dev;
 351        int ret;
 352
 353        indio_dev = devm_iio_device_alloc(&client->dev,
 354                                          sizeof(struct pa12203001_data));
 355        if (!indio_dev)
 356                return -ENOMEM;
 357
 358        data = iio_priv(indio_dev);
 359        i2c_set_clientdata(client, indio_dev);
 360        data->client = client;
 361
 362        data->map = devm_regmap_init_i2c(client, &pa12203001_regmap_config);
 363        if (IS_ERR(data->map))
 364                return PTR_ERR(data->map);
 365
 366        mutex_init(&data->lock);
 367
 368        indio_dev->dev.parent = &client->dev;
 369        indio_dev->info = &pa12203001_info;
 370        indio_dev->name = PA12203001_DRIVER_NAME;
 371        indio_dev->channels = pa12203001_channels;
 372        indio_dev->num_channels = ARRAY_SIZE(pa12203001_channels);
 373        indio_dev->modes = INDIO_DIRECT_MODE;
 374
 375        ret = pa12203001_init(indio_dev);
 376        if (ret < 0)
 377                return ret;
 378
 379        ret = pa12203001_power_chip(indio_dev, PA12203001_CHIP_ENABLE);
 380        if (ret < 0)
 381                return ret;
 382
 383        ret = pm_runtime_set_active(&client->dev);
 384        if (ret < 0)
 385                goto out_err;
 386
 387        pm_runtime_enable(&client->dev);
 388        pm_runtime_set_autosuspend_delay(&client->dev,
 389                                         PA12203001_SLEEP_DELAY_MS);
 390        pm_runtime_use_autosuspend(&client->dev);
 391
 392        ret = iio_device_register(indio_dev);
 393        if (ret < 0)
 394                goto out_err;
 395
 396        return 0;
 397
 398out_err:
 399        pa12203001_power_chip(indio_dev, PA12203001_CHIP_DISABLE);
 400        return ret;
 401}
 402
 403static int pa12203001_remove(struct i2c_client *client)
 404{
 405        struct iio_dev *indio_dev = i2c_get_clientdata(client);
 406
 407        iio_device_unregister(indio_dev);
 408
 409        pm_runtime_disable(&client->dev);
 410        pm_runtime_set_suspended(&client->dev);
 411
 412        return pa12203001_power_chip(indio_dev, PA12203001_CHIP_DISABLE);
 413}
 414
 415#if defined(CONFIG_PM_SLEEP) || defined(CONFIG_PM)
 416static int pa12203001_suspend(struct device *dev)
 417{
 418        struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
 419
 420        return pa12203001_power_chip(indio_dev, PA12203001_CHIP_DISABLE);
 421}
 422#endif
 423
 424#ifdef CONFIG_PM_SLEEP
 425static int pa12203001_resume(struct device *dev)
 426{
 427        struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
 428
 429        return pa12203001_power_chip(indio_dev, PA12203001_CHIP_ENABLE);
 430}
 431#endif
 432
 433#ifdef CONFIG_PM
 434static int pa12203001_runtime_resume(struct device *dev)
 435{
 436        struct pa12203001_data *data;
 437
 438        data = iio_priv(i2c_get_clientdata(to_i2c_client(dev)));
 439
 440        mutex_lock(&data->lock);
 441        if (data->als_needs_enable) {
 442                pa12203001_als_enable(data, PA12203001_ALS_EN_MASK);
 443                data->als_needs_enable = false;
 444        }
 445        if (data->px_needs_enable) {
 446                pa12203001_px_enable(data, PA12203001_PX_EN_MASK);
 447                data->px_needs_enable = false;
 448        }
 449        mutex_unlock(&data->lock);
 450
 451        return 0;
 452}
 453#endif
 454
 455static const struct dev_pm_ops pa12203001_pm_ops = {
 456        SET_SYSTEM_SLEEP_PM_OPS(pa12203001_suspend, pa12203001_resume)
 457        SET_RUNTIME_PM_OPS(pa12203001_suspend, pa12203001_runtime_resume, NULL)
 458};
 459
 460static const struct acpi_device_id pa12203001_acpi_match[] = {
 461        { "TXCPA122", 0},
 462        {}
 463};
 464
 465MODULE_DEVICE_TABLE(acpi, pa12203001_acpi_match);
 466
 467static const struct i2c_device_id pa12203001_id[] = {
 468                {"txcpa122", 0},
 469                {}
 470};
 471
 472MODULE_DEVICE_TABLE(i2c, pa12203001_id);
 473
 474static struct i2c_driver pa12203001_driver = {
 475        .driver = {
 476                .name = PA12203001_DRIVER_NAME,
 477                .pm = &pa12203001_pm_ops,
 478                .acpi_match_table = ACPI_PTR(pa12203001_acpi_match),
 479        },
 480        .probe = pa12203001_probe,
 481        .remove = pa12203001_remove,
 482        .id_table = pa12203001_id,
 483
 484};
 485module_i2c_driver(pa12203001_driver);
 486
 487MODULE_AUTHOR("Adriana Reus <adriana.reus@intel.com>");
 488MODULE_DESCRIPTION("Driver for TXC PA12203001 Proximity and Light Sensor");
 489MODULE_LICENSE("GPL v2");
 490