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