linux/drivers/misc/tsl2550.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 *  tsl2550.c - Linux kernel modules for ambient light sensor
   4 *
   5 *  Copyright (C) 2007 Rodolfo Giometti <giometti@linux.it>
   6 *  Copyright (C) 2007 Eurotech S.p.A. <info@eurotech.it>
   7 */
   8
   9#include <linux/module.h>
  10#include <linux/slab.h>
  11#include <linux/i2c.h>
  12#include <linux/mutex.h>
  13
  14#define TSL2550_DRV_NAME        "tsl2550"
  15#define DRIVER_VERSION          "1.2"
  16
  17/*
  18 * Defines
  19 */
  20
  21#define TSL2550_POWER_DOWN              0x00
  22#define TSL2550_POWER_UP                0x03
  23#define TSL2550_STANDARD_RANGE          0x18
  24#define TSL2550_EXTENDED_RANGE          0x1d
  25#define TSL2550_READ_ADC0               0x43
  26#define TSL2550_READ_ADC1               0x83
  27
  28/*
  29 * Structs
  30 */
  31
  32struct tsl2550_data {
  33        struct i2c_client *client;
  34        struct mutex update_lock;
  35
  36        unsigned int power_state:1;
  37        unsigned int operating_mode:1;
  38};
  39
  40/*
  41 * Global data
  42 */
  43
  44static const u8 TSL2550_MODE_RANGE[2] = {
  45        TSL2550_STANDARD_RANGE, TSL2550_EXTENDED_RANGE,
  46};
  47
  48/*
  49 * Management functions
  50 */
  51
  52static int tsl2550_set_operating_mode(struct i2c_client *client, int mode)
  53{
  54        struct tsl2550_data *data = i2c_get_clientdata(client);
  55
  56        int ret = i2c_smbus_write_byte(client, TSL2550_MODE_RANGE[mode]);
  57
  58        data->operating_mode = mode;
  59
  60        return ret;
  61}
  62
  63static int tsl2550_set_power_state(struct i2c_client *client, int state)
  64{
  65        struct tsl2550_data *data = i2c_get_clientdata(client);
  66        int ret;
  67
  68        if (state == 0)
  69                ret = i2c_smbus_write_byte(client, TSL2550_POWER_DOWN);
  70        else {
  71                ret = i2c_smbus_write_byte(client, TSL2550_POWER_UP);
  72
  73                /* On power up we should reset operating mode also... */
  74                tsl2550_set_operating_mode(client, data->operating_mode);
  75        }
  76
  77        data->power_state = state;
  78
  79        return ret;
  80}
  81
  82static int tsl2550_get_adc_value(struct i2c_client *client, u8 cmd)
  83{
  84        int ret;
  85
  86        ret = i2c_smbus_read_byte_data(client, cmd);
  87        if (ret < 0)
  88                return ret;
  89        if (!(ret & 0x80))
  90                return -EAGAIN;
  91        return ret & 0x7f;      /* remove the "valid" bit */
  92}
  93
  94/*
  95 * LUX calculation
  96 */
  97
  98#define TSL2550_MAX_LUX         1846
  99
 100static const u8 ratio_lut[] = {
 101        100, 100, 100, 100, 100, 100, 100, 100,
 102        100, 100, 100, 100, 100, 100, 99, 99,
 103        99, 99, 99, 99, 99, 99, 99, 99,
 104        99, 99, 99, 98, 98, 98, 98, 98,
 105        98, 98, 97, 97, 97, 97, 97, 96,
 106        96, 96, 96, 95, 95, 95, 94, 94,
 107        93, 93, 93, 92, 92, 91, 91, 90,
 108        89, 89, 88, 87, 87, 86, 85, 84,
 109        83, 82, 81, 80, 79, 78, 77, 75,
 110        74, 73, 71, 69, 68, 66, 64, 62,
 111        60, 58, 56, 54, 52, 49, 47, 44,
 112        42, 41, 40, 40, 39, 39, 38, 38,
 113        37, 37, 37, 36, 36, 36, 35, 35,
 114        35, 35, 34, 34, 34, 34, 33, 33,
 115        33, 33, 32, 32, 32, 32, 32, 31,
 116        31, 31, 31, 31, 30, 30, 30, 30,
 117        30,
 118};
 119
 120static const u16 count_lut[] = {
 121        0, 1, 2, 3, 4, 5, 6, 7,
 122        8, 9, 10, 11, 12, 13, 14, 15,
 123        16, 18, 20, 22, 24, 26, 28, 30,
 124        32, 34, 36, 38, 40, 42, 44, 46,
 125        49, 53, 57, 61, 65, 69, 73, 77,
 126        81, 85, 89, 93, 97, 101, 105, 109,
 127        115, 123, 131, 139, 147, 155, 163, 171,
 128        179, 187, 195, 203, 211, 219, 227, 235,
 129        247, 263, 279, 295, 311, 327, 343, 359,
 130        375, 391, 407, 423, 439, 455, 471, 487,
 131        511, 543, 575, 607, 639, 671, 703, 735,
 132        767, 799, 831, 863, 895, 927, 959, 991,
 133        1039, 1103, 1167, 1231, 1295, 1359, 1423, 1487,
 134        1551, 1615, 1679, 1743, 1807, 1871, 1935, 1999,
 135        2095, 2223, 2351, 2479, 2607, 2735, 2863, 2991,
 136        3119, 3247, 3375, 3503, 3631, 3759, 3887, 4015,
 137};
 138
 139/*
 140 * This function is described into Taos TSL2550 Designer's Notebook
 141 * pages 2, 3.
 142 */
 143static int tsl2550_calculate_lux(u8 ch0, u8 ch1)
 144{
 145        unsigned int lux;
 146
 147        /* Look up count from channel values */
 148        u16 c0 = count_lut[ch0];
 149        u16 c1 = count_lut[ch1];
 150
 151        /* Avoid division by 0 and count 1 cannot be greater than count 0 */
 152        if (c1 <= c0)
 153                if (c0) {
 154                        /*
 155                         * Calculate ratio.
 156                         * Note: the "128" is a scaling factor
 157                         */
 158                        u8 r = c1 * 128 / c0;
 159
 160                        /* Calculate LUX */
 161                        lux = ((c0 - c1) * ratio_lut[r]) / 256;
 162                } else
 163                        lux = 0;
 164        else
 165                return 0;
 166
 167        /* LUX range check */
 168        return lux > TSL2550_MAX_LUX ? TSL2550_MAX_LUX : lux;
 169}
 170
 171/*
 172 * SysFS support
 173 */
 174
 175static ssize_t tsl2550_show_power_state(struct device *dev,
 176                struct device_attribute *attr, char *buf)
 177{
 178        struct tsl2550_data *data = i2c_get_clientdata(to_i2c_client(dev));
 179
 180        return sprintf(buf, "%u\n", data->power_state);
 181}
 182
 183static ssize_t tsl2550_store_power_state(struct device *dev,
 184                struct device_attribute *attr, const char *buf, size_t count)
 185{
 186        struct i2c_client *client = to_i2c_client(dev);
 187        struct tsl2550_data *data = i2c_get_clientdata(client);
 188        unsigned long val = simple_strtoul(buf, NULL, 10);
 189        int ret;
 190
 191        if (val > 1)
 192                return -EINVAL;
 193
 194        mutex_lock(&data->update_lock);
 195        ret = tsl2550_set_power_state(client, val);
 196        mutex_unlock(&data->update_lock);
 197
 198        if (ret < 0)
 199                return ret;
 200
 201        return count;
 202}
 203
 204static DEVICE_ATTR(power_state, S_IWUSR | S_IRUGO,
 205                   tsl2550_show_power_state, tsl2550_store_power_state);
 206
 207static ssize_t tsl2550_show_operating_mode(struct device *dev,
 208                struct device_attribute *attr, char *buf)
 209{
 210        struct tsl2550_data *data = i2c_get_clientdata(to_i2c_client(dev));
 211
 212        return sprintf(buf, "%u\n", data->operating_mode);
 213}
 214
 215static ssize_t tsl2550_store_operating_mode(struct device *dev,
 216                struct device_attribute *attr, const char *buf, size_t count)
 217{
 218        struct i2c_client *client = to_i2c_client(dev);
 219        struct tsl2550_data *data = i2c_get_clientdata(client);
 220        unsigned long val = simple_strtoul(buf, NULL, 10);
 221        int ret;
 222
 223        if (val > 1)
 224                return -EINVAL;
 225
 226        if (data->power_state == 0)
 227                return -EBUSY;
 228
 229        mutex_lock(&data->update_lock);
 230        ret = tsl2550_set_operating_mode(client, val);
 231        mutex_unlock(&data->update_lock);
 232
 233        if (ret < 0)
 234                return ret;
 235
 236        return count;
 237}
 238
 239static DEVICE_ATTR(operating_mode, S_IWUSR | S_IRUGO,
 240                   tsl2550_show_operating_mode, tsl2550_store_operating_mode);
 241
 242static ssize_t __tsl2550_show_lux(struct i2c_client *client, char *buf)
 243{
 244        struct tsl2550_data *data = i2c_get_clientdata(client);
 245        u8 ch0, ch1;
 246        int ret;
 247
 248        ret = tsl2550_get_adc_value(client, TSL2550_READ_ADC0);
 249        if (ret < 0)
 250                return ret;
 251        ch0 = ret;
 252
 253        ret = tsl2550_get_adc_value(client, TSL2550_READ_ADC1);
 254        if (ret < 0)
 255                return ret;
 256        ch1 = ret;
 257
 258        /* Do the job */
 259        ret = tsl2550_calculate_lux(ch0, ch1);
 260        if (ret < 0)
 261                return ret;
 262        if (data->operating_mode == 1)
 263                ret *= 5;
 264
 265        return sprintf(buf, "%d\n", ret);
 266}
 267
 268static ssize_t tsl2550_show_lux1_input(struct device *dev,
 269                        struct device_attribute *attr, char *buf)
 270{
 271        struct i2c_client *client = to_i2c_client(dev);
 272        struct tsl2550_data *data = i2c_get_clientdata(client);
 273        int ret;
 274
 275        /* No LUX data if not operational */
 276        if (!data->power_state)
 277                return -EBUSY;
 278
 279        mutex_lock(&data->update_lock);
 280        ret = __tsl2550_show_lux(client, buf);
 281        mutex_unlock(&data->update_lock);
 282
 283        return ret;
 284}
 285
 286static DEVICE_ATTR(lux1_input, S_IRUGO,
 287                   tsl2550_show_lux1_input, NULL);
 288
 289static struct attribute *tsl2550_attributes[] = {
 290        &dev_attr_power_state.attr,
 291        &dev_attr_operating_mode.attr,
 292        &dev_attr_lux1_input.attr,
 293        NULL
 294};
 295
 296static const struct attribute_group tsl2550_attr_group = {
 297        .attrs = tsl2550_attributes,
 298};
 299
 300/*
 301 * Initialization function
 302 */
 303
 304static int tsl2550_init_client(struct i2c_client *client)
 305{
 306        struct tsl2550_data *data = i2c_get_clientdata(client);
 307        int err;
 308
 309        /*
 310         * Probe the chip. To do so we try to power up the device and then to
 311         * read back the 0x03 code
 312         */
 313        err = i2c_smbus_read_byte_data(client, TSL2550_POWER_UP);
 314        if (err < 0)
 315                return err;
 316        if (err != TSL2550_POWER_UP)
 317                return -ENODEV;
 318        data->power_state = 1;
 319
 320        /* Set the default operating mode */
 321        err = i2c_smbus_write_byte(client,
 322                                   TSL2550_MODE_RANGE[data->operating_mode]);
 323        if (err < 0)
 324                return err;
 325
 326        return 0;
 327}
 328
 329/*
 330 * I2C init/probing/exit functions
 331 */
 332
 333static struct i2c_driver tsl2550_driver;
 334static int tsl2550_probe(struct i2c_client *client,
 335                                   const struct i2c_device_id *id)
 336{
 337        struct i2c_adapter *adapter = client->adapter;
 338        struct tsl2550_data *data;
 339        int *opmode, err = 0;
 340
 341        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE
 342                                            | I2C_FUNC_SMBUS_READ_BYTE_DATA)) {
 343                err = -EIO;
 344                goto exit;
 345        }
 346
 347        data = kzalloc(sizeof(struct tsl2550_data), GFP_KERNEL);
 348        if (!data) {
 349                err = -ENOMEM;
 350                goto exit;
 351        }
 352        data->client = client;
 353        i2c_set_clientdata(client, data);
 354
 355        /* Check platform data */
 356        opmode = client->dev.platform_data;
 357        if (opmode) {
 358                if (*opmode < 0 || *opmode > 1) {
 359                        dev_err(&client->dev, "invalid operating_mode (%d)\n",
 360                                        *opmode);
 361                        err = -EINVAL;
 362                        goto exit_kfree;
 363                }
 364                data->operating_mode = *opmode;
 365        } else
 366                data->operating_mode = 0;       /* default mode is standard */
 367        dev_info(&client->dev, "%s operating mode\n",
 368                        data->operating_mode ? "extended" : "standard");
 369
 370        mutex_init(&data->update_lock);
 371
 372        /* Initialize the TSL2550 chip */
 373        err = tsl2550_init_client(client);
 374        if (err)
 375                goto exit_kfree;
 376
 377        /* Register sysfs hooks */
 378        err = sysfs_create_group(&client->dev.kobj, &tsl2550_attr_group);
 379        if (err)
 380                goto exit_kfree;
 381
 382        dev_info(&client->dev, "support ver. %s enabled\n", DRIVER_VERSION);
 383
 384        return 0;
 385
 386exit_kfree:
 387        kfree(data);
 388exit:
 389        return err;
 390}
 391
 392static int tsl2550_remove(struct i2c_client *client)
 393{
 394        sysfs_remove_group(&client->dev.kobj, &tsl2550_attr_group);
 395
 396        /* Power down the device */
 397        tsl2550_set_power_state(client, 0);
 398
 399        kfree(i2c_get_clientdata(client));
 400
 401        return 0;
 402}
 403
 404#ifdef CONFIG_PM_SLEEP
 405
 406static int tsl2550_suspend(struct device *dev)
 407{
 408        return tsl2550_set_power_state(to_i2c_client(dev), 0);
 409}
 410
 411static int tsl2550_resume(struct device *dev)
 412{
 413        return tsl2550_set_power_state(to_i2c_client(dev), 1);
 414}
 415
 416static SIMPLE_DEV_PM_OPS(tsl2550_pm_ops, tsl2550_suspend, tsl2550_resume);
 417#define TSL2550_PM_OPS (&tsl2550_pm_ops)
 418
 419#else
 420
 421#define TSL2550_PM_OPS NULL
 422
 423#endif /* CONFIG_PM_SLEEP */
 424
 425static const struct i2c_device_id tsl2550_id[] = {
 426        { "tsl2550", 0 },
 427        { }
 428};
 429MODULE_DEVICE_TABLE(i2c, tsl2550_id);
 430
 431static const struct of_device_id tsl2550_of_match[] = {
 432        { .compatible = "taos,tsl2550" },
 433        { }
 434};
 435MODULE_DEVICE_TABLE(of, tsl2550_of_match);
 436
 437static struct i2c_driver tsl2550_driver = {
 438        .driver = {
 439                .name   = TSL2550_DRV_NAME,
 440                .of_match_table = tsl2550_of_match,
 441                .pm     = TSL2550_PM_OPS,
 442        },
 443        .probe  = tsl2550_probe,
 444        .remove = tsl2550_remove,
 445        .id_table = tsl2550_id,
 446};
 447
 448module_i2c_driver(tsl2550_driver);
 449
 450MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>");
 451MODULE_DESCRIPTION("TSL2550 ambient light sensor driver");
 452MODULE_LICENSE("GPL");
 453MODULE_VERSION(DRIVER_VERSION);
 454