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