xref: /openbmc/linux/drivers/misc/tsl2550.c (revision 6aa7de05)
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 const struct of_device_id tsl2550_of_match[] = {
447 	{ .compatible = "taos,tsl2550" },
448 	{ }
449 };
450 MODULE_DEVICE_TABLE(of, tsl2550_of_match);
451 
452 static 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 
463 module_i2c_driver(tsl2550_driver);
464 
465 MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>");
466 MODULE_DESCRIPTION("TSL2550 ambient light sensor driver");
467 MODULE_LICENSE("GPL");
468 MODULE_VERSION(DRIVER_VERSION);
469