Loading...
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
46struct 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
58static const u8 TSL2550_MODE_RANGE[2] = {
59 TSL2550_STANDARD_RANGE, TSL2550_EXTENDED_RANGE,
60};
61
62/*
63 * Management functions
64 */
65
66static 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
77static 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
96static 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
114static 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
134static 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 */
157static 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
191static 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
199static 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
220static DEVICE_ATTR(power_state, S_IWUSR | S_IRUGO,
221 tsl2550_show_power_state, tsl2550_store_power_state);
222
223static 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
231static 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
255static DEVICE_ATTR(operating_mode, S_IWUSR | S_IRUGO,
256 tsl2550_show_operating_mode, tsl2550_store_operating_mode);
257
258static 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
284static 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
302static DEVICE_ATTR(lux1_input, S_IRUGO,
303 tsl2550_show_lux1_input, NULL);
304
305static 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
312static const struct attribute_group tsl2550_attr_group = {
313 .attrs = tsl2550_attributes,
314};
315
316/*
317 * Initialization function
318 */
319
320static 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
349static struct i2c_driver tsl2550_driver;
350static 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
402exit_kfree:
403 kfree(data);
404exit:
405 return err;
406}
407
408static 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
422static int tsl2550_suspend(struct i2c_client *client, pm_message_t mesg)
423{
424 return tsl2550_set_power_state(client, 0);
425}
426
427static 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
439static const struct i2c_device_id tsl2550_id[] = {
440 { "tsl2550", 0 },
441 { }
442};
443MODULE_DEVICE_TABLE(i2c, tsl2550_id);
444
445static 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
457static int __init tsl2550_init(void)
458{
459 return i2c_add_driver(&tsl2550_driver);
460}
461
462static void __exit tsl2550_exit(void)
463{
464 i2c_del_driver(&tsl2550_driver);
465}
466
467MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>");
468MODULE_DESCRIPTION("TSL2550 ambient light sensor driver");
469MODULE_LICENSE("GPL");
470MODULE_VERSION(DRIVER_VERSION);
471
472module_init(tsl2550_init);
473module_exit(tsl2550_exit);
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 const struct of_device_id tsl2550_of_match[] = {
447 { .compatible = "taos,tsl2550" },
448 { }
449};
450MODULE_DEVICE_TABLE(of, tsl2550_of_match);
451
452static struct i2c_driver tsl2550_driver = {
453 .driver = {
454 .name = TSL2550_DRV_NAME,
455 .of_match_table = tsl2550_of_match,
456 .pm = TSL2550_PM_OPS,
457 },
458 .probe = tsl2550_probe,
459 .remove = tsl2550_remove,
460 .id_table = tsl2550_id,
461};
462
463module_i2c_driver(tsl2550_driver);
464
465MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>");
466MODULE_DESCRIPTION("TSL2550 ambient light sensor driver");
467MODULE_LICENSE("GPL");
468MODULE_VERSION(DRIVER_VERSION);