root/drivers/misc/tsl2550.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. tsl2550_set_operating_mode
  2. tsl2550_set_power_state
  3. tsl2550_get_adc_value
  4. tsl2550_calculate_lux
  5. tsl2550_show_power_state
  6. tsl2550_store_power_state
  7. tsl2550_show_operating_mode
  8. tsl2550_store_operating_mode
  9. __tsl2550_show_lux
  10. tsl2550_show_lux1_input
  11. tsl2550_init_client
  12. tsl2550_probe
  13. tsl2550_remove
  14. tsl2550_suspend
  15. tsl2550_resume

   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 
  32 struct 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 
  44 static const u8 TSL2550_MODE_RANGE[2] = {
  45         TSL2550_STANDARD_RANGE, TSL2550_EXTENDED_RANGE,
  46 };
  47 
  48 /*
  49  * Management functions
  50  */
  51 
  52 static 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 
  63 static 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 
  82 static 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 
 100 static 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 
 120 static 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  */
 143 static 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         /*
 152          * Calculate ratio.
 153          * Note: the "128" is a scaling factor
 154          */
 155         u8 r = 128;
 156 
 157         /* Avoid division by 0 and count 1 cannot be greater than count 0 */
 158         if (c1 <= c0)
 159                 if (c0) {
 160                         r = c1 * 128 / c0;
 161 
 162                         /* Calculate LUX */
 163                         lux = ((c0 - c1) * ratio_lut[r]) / 256;
 164                 } else
 165                         lux = 0;
 166         else
 167                 return 0;
 168 
 169         /* LUX range check */
 170         return lux > TSL2550_MAX_LUX ? TSL2550_MAX_LUX : lux;
 171 }
 172 
 173 /*
 174  * SysFS support
 175  */
 176 
 177 static ssize_t tsl2550_show_power_state(struct device *dev,
 178                 struct device_attribute *attr, char *buf)
 179 {
 180         struct tsl2550_data *data = i2c_get_clientdata(to_i2c_client(dev));
 181 
 182         return sprintf(buf, "%u\n", data->power_state);
 183 }
 184 
 185 static ssize_t tsl2550_store_power_state(struct device *dev,
 186                 struct device_attribute *attr, const char *buf, size_t count)
 187 {
 188         struct i2c_client *client = to_i2c_client(dev);
 189         struct tsl2550_data *data = i2c_get_clientdata(client);
 190         unsigned long val = simple_strtoul(buf, NULL, 10);
 191         int ret;
 192 
 193         if (val > 1)
 194                 return -EINVAL;
 195 
 196         mutex_lock(&data->update_lock);
 197         ret = tsl2550_set_power_state(client, val);
 198         mutex_unlock(&data->update_lock);
 199 
 200         if (ret < 0)
 201                 return ret;
 202 
 203         return count;
 204 }
 205 
 206 static DEVICE_ATTR(power_state, S_IWUSR | S_IRUGO,
 207                    tsl2550_show_power_state, tsl2550_store_power_state);
 208 
 209 static ssize_t tsl2550_show_operating_mode(struct device *dev,
 210                 struct device_attribute *attr, char *buf)
 211 {
 212         struct tsl2550_data *data = i2c_get_clientdata(to_i2c_client(dev));
 213 
 214         return sprintf(buf, "%u\n", data->operating_mode);
 215 }
 216 
 217 static ssize_t tsl2550_store_operating_mode(struct device *dev,
 218                 struct device_attribute *attr, const char *buf, size_t count)
 219 {
 220         struct i2c_client *client = to_i2c_client(dev);
 221         struct tsl2550_data *data = i2c_get_clientdata(client);
 222         unsigned long val = simple_strtoul(buf, NULL, 10);
 223         int ret;
 224 
 225         if (val > 1)
 226                 return -EINVAL;
 227 
 228         if (data->power_state == 0)
 229                 return -EBUSY;
 230 
 231         mutex_lock(&data->update_lock);
 232         ret = tsl2550_set_operating_mode(client, val);
 233         mutex_unlock(&data->update_lock);
 234 
 235         if (ret < 0)
 236                 return ret;
 237 
 238         return count;
 239 }
 240 
 241 static DEVICE_ATTR(operating_mode, S_IWUSR | S_IRUGO,
 242                    tsl2550_show_operating_mode, tsl2550_store_operating_mode);
 243 
 244 static ssize_t __tsl2550_show_lux(struct i2c_client *client, char *buf)
 245 {
 246         struct tsl2550_data *data = i2c_get_clientdata(client);
 247         u8 ch0, ch1;
 248         int ret;
 249 
 250         ret = tsl2550_get_adc_value(client, TSL2550_READ_ADC0);
 251         if (ret < 0)
 252                 return ret;
 253         ch0 = ret;
 254 
 255         ret = tsl2550_get_adc_value(client, TSL2550_READ_ADC1);
 256         if (ret < 0)
 257                 return ret;
 258         ch1 = ret;
 259 
 260         /* Do the job */
 261         ret = tsl2550_calculate_lux(ch0, ch1);
 262         if (ret < 0)
 263                 return ret;
 264         if (data->operating_mode == 1)
 265                 ret *= 5;
 266 
 267         return sprintf(buf, "%d\n", ret);
 268 }
 269 
 270 static ssize_t tsl2550_show_lux1_input(struct device *dev,
 271                         struct device_attribute *attr, char *buf)
 272 {
 273         struct i2c_client *client = to_i2c_client(dev);
 274         struct tsl2550_data *data = i2c_get_clientdata(client);
 275         int ret;
 276 
 277         /* No LUX data if not operational */
 278         if (!data->power_state)
 279                 return -EBUSY;
 280 
 281         mutex_lock(&data->update_lock);
 282         ret = __tsl2550_show_lux(client, buf);
 283         mutex_unlock(&data->update_lock);
 284 
 285         return ret;
 286 }
 287 
 288 static DEVICE_ATTR(lux1_input, S_IRUGO,
 289                    tsl2550_show_lux1_input, NULL);
 290 
 291 static struct attribute *tsl2550_attributes[] = {
 292         &dev_attr_power_state.attr,
 293         &dev_attr_operating_mode.attr,
 294         &dev_attr_lux1_input.attr,
 295         NULL
 296 };
 297 
 298 static const struct attribute_group tsl2550_attr_group = {
 299         .attrs = tsl2550_attributes,
 300 };
 301 
 302 /*
 303  * Initialization function
 304  */
 305 
 306 static int tsl2550_init_client(struct i2c_client *client)
 307 {
 308         struct tsl2550_data *data = i2c_get_clientdata(client);
 309         int err;
 310 
 311         /*
 312          * Probe the chip. To do so we try to power up the device and then to
 313          * read back the 0x03 code
 314          */
 315         err = i2c_smbus_read_byte_data(client, TSL2550_POWER_UP);
 316         if (err < 0)
 317                 return err;
 318         if (err != TSL2550_POWER_UP)
 319                 return -ENODEV;
 320         data->power_state = 1;
 321 
 322         /* Set the default operating mode */
 323         err = i2c_smbus_write_byte(client,
 324                                    TSL2550_MODE_RANGE[data->operating_mode]);
 325         if (err < 0)
 326                 return err;
 327 
 328         return 0;
 329 }
 330 
 331 /*
 332  * I2C init/probing/exit functions
 333  */
 334 
 335 static struct i2c_driver tsl2550_driver;
 336 static int tsl2550_probe(struct i2c_client *client,
 337                                    const struct i2c_device_id *id)
 338 {
 339         struct i2c_adapter *adapter = client->adapter;
 340         struct tsl2550_data *data;
 341         int *opmode, err = 0;
 342 
 343         if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE
 344                                             | I2C_FUNC_SMBUS_READ_BYTE_DATA)) {
 345                 err = -EIO;
 346                 goto exit;
 347         }
 348 
 349         data = kzalloc(sizeof(struct tsl2550_data), GFP_KERNEL);
 350         if (!data) {
 351                 err = -ENOMEM;
 352                 goto exit;
 353         }
 354         data->client = client;
 355         i2c_set_clientdata(client, data);
 356 
 357         /* Check platform data */
 358         opmode = client->dev.platform_data;
 359         if (opmode) {
 360                 if (*opmode < 0 || *opmode > 1) {
 361                         dev_err(&client->dev, "invalid operating_mode (%d)\n",
 362                                         *opmode);
 363                         err = -EINVAL;
 364                         goto exit_kfree;
 365                 }
 366                 data->operating_mode = *opmode;
 367         } else
 368                 data->operating_mode = 0;       /* default mode is standard */
 369         dev_info(&client->dev, "%s operating mode\n",
 370                         data->operating_mode ? "extended" : "standard");
 371 
 372         mutex_init(&data->update_lock);
 373 
 374         /* Initialize the TSL2550 chip */
 375         err = tsl2550_init_client(client);
 376         if (err)
 377                 goto exit_kfree;
 378 
 379         /* Register sysfs hooks */
 380         err = sysfs_create_group(&client->dev.kobj, &tsl2550_attr_group);
 381         if (err)
 382                 goto exit_kfree;
 383 
 384         dev_info(&client->dev, "support ver. %s enabled\n", DRIVER_VERSION);
 385 
 386         return 0;
 387 
 388 exit_kfree:
 389         kfree(data);
 390 exit:
 391         return err;
 392 }
 393 
 394 static int tsl2550_remove(struct i2c_client *client)
 395 {
 396         sysfs_remove_group(&client->dev.kobj, &tsl2550_attr_group);
 397 
 398         /* Power down the device */
 399         tsl2550_set_power_state(client, 0);
 400 
 401         kfree(i2c_get_clientdata(client));
 402 
 403         return 0;
 404 }
 405 
 406 #ifdef CONFIG_PM_SLEEP
 407 
 408 static int tsl2550_suspend(struct device *dev)
 409 {
 410         return tsl2550_set_power_state(to_i2c_client(dev), 0);
 411 }
 412 
 413 static int tsl2550_resume(struct device *dev)
 414 {
 415         return tsl2550_set_power_state(to_i2c_client(dev), 1);
 416 }
 417 
 418 static SIMPLE_DEV_PM_OPS(tsl2550_pm_ops, tsl2550_suspend, tsl2550_resume);
 419 #define TSL2550_PM_OPS (&tsl2550_pm_ops)
 420 
 421 #else
 422 
 423 #define TSL2550_PM_OPS NULL
 424 
 425 #endif /* CONFIG_PM_SLEEP */
 426 
 427 static const struct i2c_device_id tsl2550_id[] = {
 428         { "tsl2550", 0 },
 429         { }
 430 };
 431 MODULE_DEVICE_TABLE(i2c, tsl2550_id);
 432 
 433 static const struct of_device_id tsl2550_of_match[] = {
 434         { .compatible = "taos,tsl2550" },
 435         { }
 436 };
 437 MODULE_DEVICE_TABLE(of, tsl2550_of_match);
 438 
 439 static struct i2c_driver tsl2550_driver = {
 440         .driver = {
 441                 .name   = TSL2550_DRV_NAME,
 442                 .of_match_table = tsl2550_of_match,
 443                 .pm     = TSL2550_PM_OPS,
 444         },
 445         .probe  = tsl2550_probe,
 446         .remove = tsl2550_remove,
 447         .id_table = tsl2550_id,
 448 };
 449 
 450 module_i2c_driver(tsl2550_driver);
 451 
 452 MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>");
 453 MODULE_DESCRIPTION("TSL2550 ambient light sensor driver");
 454 MODULE_LICENSE("GPL");
 455 MODULE_VERSION(DRIVER_VERSION);

/* [<][>][^][v][top][bottom][index][help] */