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