]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/misc/tsl2550.c
mxc: vpu: improve clk enable/disable handling
[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/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
45 struct 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
57 static const u8 TSL2550_MODE_RANGE[2] = {
58         TSL2550_STANDARD_RANGE, TSL2550_EXTENDED_RANGE,
59 };
60
61 /*
62  * Management functions
63  */
64
65 static 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
76 static 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
95 static 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
113 static 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
133 static 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  */
156 static 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
190 static 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
198 static 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
219 static DEVICE_ATTR(power_state, S_IWUSR | S_IRUGO,
220                    tsl2550_show_power_state, tsl2550_store_power_state);
221
222 static 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
230 static 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
254 static DEVICE_ATTR(operating_mode, S_IWUSR | S_IRUGO,
255                    tsl2550_show_operating_mode, tsl2550_store_operating_mode);
256
257 static 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
283 static 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
301 static DEVICE_ATTR(lux1_input, S_IRUGO,
302                    tsl2550_show_lux1_input, NULL);
303
304 static 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
311 static const struct attribute_group tsl2550_attr_group = {
312         .attrs = tsl2550_attributes,
313 };
314
315 /*
316  * Initialization function
317  */
318
319 static 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
348 static struct i2c_driver tsl2550_driver;
349 static 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
401 exit_kfree:
402         kfree(data);
403 exit:
404         return err;
405 }
406
407 static 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
421 static int tsl2550_suspend(struct device *dev)
422 {
423         return tsl2550_set_power_state(to_i2c_client(dev), 0);
424 }
425
426 static int tsl2550_resume(struct device *dev)
427 {
428         return tsl2550_set_power_state(to_i2c_client(dev), 1);
429 }
430
431 static 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
440 static const struct i2c_device_id tsl2550_id[] = {
441         { "tsl2550", 0 },
442         { }
443 };
444 MODULE_DEVICE_TABLE(i2c, tsl2550_id);
445
446 static struct i2c_driver tsl2550_driver = {
447         .driver = {
448                 .name   = TSL2550_DRV_NAME,
449                 .owner  = THIS_MODULE,
450                 .pm     = TSL2550_PM_OPS,
451         },
452         .probe  = tsl2550_probe,
453         .remove = tsl2550_remove,
454         .id_table = tsl2550_id,
455 };
456
457 module_i2c_driver(tsl2550_driver);
458
459 MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>");
460 MODULE_DESCRIPTION("TSL2550 ambient light sensor driver");
461 MODULE_LICENSE("GPL");
462 MODULE_VERSION(DRIVER_VERSION);