xref: /openbmc/linux/drivers/misc/tsl2550.c (revision d0b73b48)
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 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 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	= 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);
463