]> err.no Git - linux-2.6/blob - drivers/i2c/chips/tsl2550.c
i2c/tsl2550: Speed up initialization
[linux-2.6] / drivers / i2c / chips / 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 #include <linux/delay.h>
28
29 #define TSL2550_DRV_NAME        "tsl2550"
30 #define DRIVER_VERSION          "1.1.1"
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
47 struct 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
59 static const u8 TSL2550_MODE_RANGE[2] = {
60         TSL2550_STANDARD_RANGE, TSL2550_EXTENDED_RANGE,
61 };
62
63 /*
64  * Management functions
65  */
66
67 static 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
78 static 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
97 static 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
134 static 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
154 static 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  */
177 static 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 (c0 && (c1 <= c0))
193                 r = c1 * 128 / c0;
194         else
195                 return -1;
196
197         /* Calculate LUX */
198         lux = ((c0 - c1) * ratio_lut[r]) / 256;
199
200         /* LUX range check */
201         return lux > TSL2550_MAX_LUX ? TSL2550_MAX_LUX : lux;
202 }
203
204 /*
205  * SysFS support
206  */
207
208 static ssize_t tsl2550_show_power_state(struct device *dev,
209                 struct device_attribute *attr, char *buf)
210 {
211         struct tsl2550_data *data = i2c_get_clientdata(to_i2c_client(dev));
212
213         return sprintf(buf, "%u\n", data->power_state);
214 }
215
216 static ssize_t tsl2550_store_power_state(struct device *dev,
217                 struct device_attribute *attr, const char *buf, size_t count)
218 {
219         struct i2c_client *client = to_i2c_client(dev);
220         struct tsl2550_data *data = i2c_get_clientdata(client);
221         unsigned long val = simple_strtoul(buf, NULL, 10);
222         int ret;
223
224         if (val < 0 || val > 1)
225                 return -EINVAL;
226
227         mutex_lock(&data->update_lock);
228         ret = tsl2550_set_power_state(client, val);
229         mutex_unlock(&data->update_lock);
230
231         if (ret < 0)
232                 return ret;
233
234         return count;
235 }
236
237 static DEVICE_ATTR(power_state, S_IWUSR | S_IRUGO,
238                    tsl2550_show_power_state, tsl2550_store_power_state);
239
240 static ssize_t tsl2550_show_operating_mode(struct device *dev,
241                 struct device_attribute *attr, char *buf)
242 {
243         struct tsl2550_data *data = i2c_get_clientdata(to_i2c_client(dev));
244
245         return sprintf(buf, "%u\n", data->operating_mode);
246 }
247
248 static ssize_t tsl2550_store_operating_mode(struct device *dev,
249                 struct device_attribute *attr, const char *buf, size_t count)
250 {
251         struct i2c_client *client = to_i2c_client(dev);
252         struct tsl2550_data *data = i2c_get_clientdata(client);
253         unsigned long val = simple_strtoul(buf, NULL, 10);
254         int ret;
255
256         if (val < 0 || val > 1)
257                 return -EINVAL;
258
259         if (data->power_state == 0)
260                 return -EBUSY;
261
262         mutex_lock(&data->update_lock);
263         ret = tsl2550_set_operating_mode(client, val);
264         mutex_unlock(&data->update_lock);
265
266         if (ret < 0)
267                 return ret;
268
269         return count;
270 }
271
272 static DEVICE_ATTR(operating_mode, S_IWUSR | S_IRUGO,
273                    tsl2550_show_operating_mode, tsl2550_store_operating_mode);
274
275 static ssize_t __tsl2550_show_lux(struct i2c_client *client, char *buf)
276 {
277         u8 ch0, ch1;
278         int ret;
279
280         ret = tsl2550_get_adc_value(client, TSL2550_READ_ADC0);
281         if (ret < 0)
282                 return ret;
283         ch0 = ret;
284
285         mdelay(1);
286
287         ret = tsl2550_get_adc_value(client, TSL2550_READ_ADC1);
288         if (ret < 0)
289                 return ret;
290         ch1 = ret;
291
292         /* Do the job */
293         ret = tsl2550_calculate_lux(ch0, ch1);
294         if (ret < 0)
295                 return ret;
296
297         return sprintf(buf, "%d\n", ret);
298 }
299
300 static ssize_t tsl2550_show_lux1_input(struct device *dev,
301                         struct device_attribute *attr, char *buf)
302 {
303         struct i2c_client *client = to_i2c_client(dev);
304         struct tsl2550_data *data = i2c_get_clientdata(client);
305         int ret;
306
307         /* No LUX data if not operational */
308         if (!data->power_state)
309                 return -EBUSY;
310
311         mutex_lock(&data->update_lock);
312         ret = __tsl2550_show_lux(client, buf);
313         mutex_unlock(&data->update_lock);
314
315         return ret;
316 }
317
318 static DEVICE_ATTR(lux1_input, S_IRUGO,
319                    tsl2550_show_lux1_input, NULL);
320
321 static struct attribute *tsl2550_attributes[] = {
322         &dev_attr_power_state.attr,
323         &dev_attr_operating_mode.attr,
324         &dev_attr_lux1_input.attr,
325         NULL
326 };
327
328 static const struct attribute_group tsl2550_attr_group = {
329         .attrs = tsl2550_attributes,
330 };
331
332 /*
333  * Initialization function
334  */
335
336 static int tsl2550_init_client(struct i2c_client *client)
337 {
338         struct tsl2550_data *data = i2c_get_clientdata(client);
339         int err;
340
341         /*
342          * Probe the chip. To do so we try to power up the device and then to
343          * read back the 0x03 code
344          */
345         err = i2c_smbus_write_byte(client, TSL2550_POWER_UP);
346         if (err < 0)
347                 return err;
348         mdelay(1);
349         if (i2c_smbus_read_byte(client) != TSL2550_POWER_UP)
350                 return -ENODEV;
351         data->power_state = 1;
352
353         /* Set the default operating mode */
354         err = i2c_smbus_write_byte(client,
355                                    TSL2550_MODE_RANGE[data->operating_mode]);
356         if (err < 0)
357                 return err;
358
359         return 0;
360 }
361
362 /*
363  * I2C init/probing/exit functions
364  */
365
366 static struct i2c_driver tsl2550_driver;
367 static int __devinit tsl2550_probe(struct i2c_client *client)
368 {
369         struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
370         struct tsl2550_data *data;
371         int *opmode, err = 0;
372
373         if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) {
374                 err = -EIO;
375                 goto exit;
376         }
377
378         data = kzalloc(sizeof(struct tsl2550_data), GFP_KERNEL);
379         if (!data) {
380                 err = -ENOMEM;
381                 goto exit;
382         }
383         data->client = client;
384         i2c_set_clientdata(client, data);
385
386         /* Check platform data */
387         opmode = client->dev.platform_data;
388         if (opmode) {
389                 if (*opmode < 0 || *opmode > 1) {
390                         dev_err(&client->dev, "invalid operating_mode (%d)\n",
391                                         *opmode);
392                         err = -EINVAL;
393                         goto exit_kfree;
394                 }
395                 data->operating_mode = *opmode;
396         } else
397                 data->operating_mode = 0;       /* default mode is standard */
398         dev_info(&client->dev, "%s operating mode\n",
399                         data->operating_mode ? "extended" : "standard");
400
401         mutex_init(&data->update_lock);
402
403         /* Initialize the TSL2550 chip */
404         err = tsl2550_init_client(client);
405         if (err)
406                 goto exit_kfree;
407
408         /* Register sysfs hooks */
409         err = sysfs_create_group(&client->dev.kobj, &tsl2550_attr_group);
410         if (err)
411                 goto exit_kfree;
412
413         dev_info(&client->dev, "support ver. %s enabled\n", DRIVER_VERSION);
414
415         return 0;
416
417 exit_kfree:
418         kfree(data);
419 exit:
420         return err;
421 }
422
423 static int __devexit tsl2550_remove(struct i2c_client *client)
424 {
425         sysfs_remove_group(&client->dev.kobj, &tsl2550_attr_group);
426
427         /* Power down the device */
428         tsl2550_set_power_state(client, 0);
429
430         kfree(i2c_get_clientdata(client));
431
432         return 0;
433 }
434
435 static struct i2c_driver tsl2550_driver = {
436         .driver = {
437                 .name   = TSL2550_DRV_NAME,
438                 .owner  = THIS_MODULE,
439         },
440         .probe  = tsl2550_probe,
441         .remove = __devexit_p(tsl2550_remove),
442 };
443
444 static int __init tsl2550_init(void)
445 {
446         return i2c_add_driver(&tsl2550_driver);
447 }
448
449 static void __exit tsl2550_exit(void)
450 {
451         i2c_del_driver(&tsl2550_driver);
452 }
453
454 MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>");
455 MODULE_DESCRIPTION("TSL2550 ambient light sensor driver");
456 MODULE_LICENSE("GPL");
457 MODULE_VERSION(DRIVER_VERSION);
458
459 module_init(tsl2550_init);
460 module_exit(tsl2550_exit);