Staging: iio: some uninitialized variable bugs
[deliverable/linux.git] / drivers / staging / iio / light / isl29018.c
CommitLineData
94042874
RK
1/*
2 * A iio driver for the light sensor ISL 29018.
3 *
4 * IIO driver for monitoring ambient light intensity in luxi, proximity
5 * sensing and infrared sensing.
6 *
7 * Copyright (c) 2010, NVIDIA Corporation.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 */
23
24#include <linux/module.h>
25#include <linux/i2c.h>
26#include <linux/err.h>
27#include <linux/mutex.h>
28#include <linux/delay.h>
29#include <linux/slab.h>
30#include "../iio.h"
31
32#define CONVERSION_TIME_MS 100
33
34#define ISL29018_REG_ADD_COMMAND1 0x00
35#define COMMMAND1_OPMODE_SHIFT 5
36#define COMMMAND1_OPMODE_MASK (7 << COMMMAND1_OPMODE_SHIFT)
37#define COMMMAND1_OPMODE_POWER_DOWN 0
38#define COMMMAND1_OPMODE_ALS_ONCE 1
39#define COMMMAND1_OPMODE_IR_ONCE 2
40#define COMMMAND1_OPMODE_PROX_ONCE 3
41
42#define ISL29018_REG_ADD_COMMANDII 0x01
43#define COMMANDII_RESOLUTION_SHIFT 2
44#define COMMANDII_RESOLUTION_MASK (0x3 << COMMANDII_RESOLUTION_SHIFT)
45
46#define COMMANDII_RANGE_SHIFT 0
47#define COMMANDII_RANGE_MASK (0x3 << COMMANDII_RANGE_SHIFT)
48
49#define COMMANDII_SCHEME_SHIFT 7
50#define COMMANDII_SCHEME_MASK (0x1 << COMMANDII_SCHEME_SHIFT)
51
52#define ISL29018_REG_ADD_DATA_LSB 0x02
53#define ISL29018_REG_ADD_DATA_MSB 0x03
54#define ISL29018_MAX_REGS ISL29018_REG_ADD_DATA_MSB
55
56struct isl29018_chip {
94042874
RK
57 struct i2c_client *client;
58 struct mutex lock;
59 unsigned int range;
60 unsigned int adc_bit;
61 int prox_scheme;
62 u8 reg_cache[ISL29018_MAX_REGS];
63};
64
65static int isl29018_write_data(struct i2c_client *client, u8 reg,
66 u8 val, u8 mask, u8 shift)
67{
68 u8 regval;
69 int ret = 0;
70 struct isl29018_chip *chip = i2c_get_clientdata(client);
71
72 regval = chip->reg_cache[reg];
73 regval &= ~mask;
74 regval |= val << shift;
75
76 ret = i2c_smbus_write_byte_data(client, reg, regval);
77 if (ret) {
78 dev_err(&client->dev, "Write to device fails status %x\n", ret);
79 return ret;
80 }
81 chip->reg_cache[reg] = regval;
82
83 return 0;
84}
85
86static int isl29018_set_range(struct i2c_client *client, unsigned long range,
87 unsigned int *new_range)
88{
89 static const unsigned long supp_ranges[] = {1000, 4000, 16000, 64000};
90 int i;
91
92 for (i = 0; i < ARRAY_SIZE(supp_ranges); ++i) {
93 if (range <= supp_ranges[i]) {
94 *new_range = (unsigned int)supp_ranges[i];
95 break;
96 }
97 }
98
99 if (i >= ARRAY_SIZE(supp_ranges))
100 return -EINVAL;
101
102 return isl29018_write_data(client, ISL29018_REG_ADD_COMMANDII,
103 i, COMMANDII_RANGE_MASK, COMMANDII_RANGE_SHIFT);
104}
105
106static int isl29018_set_resolution(struct i2c_client *client,
107 unsigned long adcbit, unsigned int *conf_adc_bit)
108{
109 static const unsigned long supp_adcbit[] = {16, 12, 8, 4};
110 int i;
111
112 for (i = 0; i < ARRAY_SIZE(supp_adcbit); ++i) {
113 if (adcbit >= supp_adcbit[i]) {
114 *conf_adc_bit = (unsigned int)supp_adcbit[i];
115 break;
116 }
117 }
118
119 if (i >= ARRAY_SIZE(supp_adcbit))
120 return -EINVAL;
121
122 return isl29018_write_data(client, ISL29018_REG_ADD_COMMANDII,
123 i, COMMANDII_RESOLUTION_MASK,
124 COMMANDII_RESOLUTION_SHIFT);
125}
126
127static int isl29018_read_sensor_input(struct i2c_client *client, int mode)
128{
129 int status;
130 int lsb;
131 int msb;
132
133 /* Set mode */
134 status = isl29018_write_data(client, ISL29018_REG_ADD_COMMAND1,
135 mode, COMMMAND1_OPMODE_MASK, COMMMAND1_OPMODE_SHIFT);
136 if (status) {
137 dev_err(&client->dev, "Error in setting operating mode\n");
138 return status;
139 }
140 msleep(CONVERSION_TIME_MS);
141 lsb = i2c_smbus_read_byte_data(client, ISL29018_REG_ADD_DATA_LSB);
142 if (lsb < 0) {
143 dev_err(&client->dev, "Error in reading LSB DATA\n");
144 return lsb;
145 }
146
147 msb = i2c_smbus_read_byte_data(client, ISL29018_REG_ADD_DATA_MSB);
148 if (msb < 0) {
149 dev_err(&client->dev, "Error in reading MSB DATA\n");
150 return msb;
151 }
152 dev_vdbg(&client->dev, "MSB 0x%x and LSB 0x%x\n", msb, lsb);
153
154 return (msb << 8) | lsb;
155}
156
157static int isl29018_read_lux(struct i2c_client *client, int *lux)
158{
159 int lux_data;
160 struct isl29018_chip *chip = i2c_get_clientdata(client);
161
162 lux_data = isl29018_read_sensor_input(client,
163 COMMMAND1_OPMODE_ALS_ONCE);
164
165 if (lux_data < 0)
166 return lux_data;
167
168 *lux = (lux_data * chip->range) >> chip->adc_bit;
169
170 return 0;
171}
172
173static int isl29018_read_ir(struct i2c_client *client, int *ir)
174{
175 int ir_data;
176
177 ir_data = isl29018_read_sensor_input(client, COMMMAND1_OPMODE_IR_ONCE);
178
179 if (ir_data < 0)
180 return ir_data;
181
182 *ir = ir_data;
183
184 return 0;
185}
186
187static int isl29018_read_proximity_ir(struct i2c_client *client, int scheme,
188 int *near_ir)
189{
190 int status;
191 int prox_data = -1;
192 int ir_data = -1;
193
194 /* Do proximity sensing with required scheme */
195 status = isl29018_write_data(client, ISL29018_REG_ADD_COMMANDII,
196 scheme, COMMANDII_SCHEME_MASK, COMMANDII_SCHEME_SHIFT);
197 if (status) {
198 dev_err(&client->dev, "Error in setting operating mode\n");
199 return status;
200 }
201
202 prox_data = isl29018_read_sensor_input(client,
203 COMMMAND1_OPMODE_PROX_ONCE);
204 if (prox_data < 0)
205 return prox_data;
206
207 if (scheme == 1) {
208 *near_ir = prox_data;
209 return 0;
210 }
211
212 ir_data = isl29018_read_sensor_input(client,
213 COMMMAND1_OPMODE_IR_ONCE);
214
215 if (ir_data < 0)
216 return ir_data;
217
218 if (prox_data >= ir_data)
219 *near_ir = prox_data - ir_data;
220 else
221 *near_ir = 0;
222
223 return 0;
224}
225
226static ssize_t get_sensor_data(struct device *dev, char *buf, int mode)
227{
228 struct iio_dev *indio_dev = dev_get_drvdata(dev);
927afbec 229 struct isl29018_chip *chip = iio_priv(indio_dev);
94042874
RK
230 struct i2c_client *client = chip->client;
231 int value = 0;
232 int status;
233
234 mutex_lock(&chip->lock);
235 switch (mode) {
236 case COMMMAND1_OPMODE_PROX_ONCE:
237 status = isl29018_read_proximity_ir(client,
238 chip->prox_scheme, &value);
239 break;
240
241 case COMMMAND1_OPMODE_ALS_ONCE:
242 status = isl29018_read_lux(client, &value);
243 break;
244
245 case COMMMAND1_OPMODE_IR_ONCE:
246 status = isl29018_read_ir(client, &value);
247 break;
248
249 default:
250 dev_err(&client->dev, "Mode %d is not supported\n", mode);
251 mutex_unlock(&chip->lock);
252 return -EBUSY;
253 }
254 if (status < 0) {
255 dev_err(&client->dev, "Error in Reading data");
256 mutex_unlock(&chip->lock);
257 return status;
258 }
259
260 mutex_unlock(&chip->lock);
261
262 return sprintf(buf, "%d\n", value);
263}
264
265/* Sysfs interface */
266/* range */
267static ssize_t show_range(struct device *dev,
268 struct device_attribute *attr, char *buf)
269{
270 struct iio_dev *indio_dev = dev_get_drvdata(dev);
927afbec 271 struct isl29018_chip *chip = iio_priv(indio_dev);
94042874
RK
272
273 return sprintf(buf, "%u\n", chip->range);
274}
275
276static ssize_t store_range(struct device *dev,
277 struct device_attribute *attr, const char *buf, size_t count)
278{
279 struct iio_dev *indio_dev = dev_get_drvdata(dev);
927afbec 280 struct isl29018_chip *chip = iio_priv(indio_dev);
94042874
RK
281 struct i2c_client *client = chip->client;
282 int status;
283 unsigned long lval;
284 unsigned int new_range;
285
286 if (strict_strtoul(buf, 10, &lval))
287 return -EINVAL;
288
289 if (!(lval == 1000UL || lval == 4000UL ||
290 lval == 16000UL || lval == 64000UL)) {
291 dev_err(dev, "The range is not supported\n");
292 return -EINVAL;
293 }
294
295 mutex_lock(&chip->lock);
296 status = isl29018_set_range(client, lval, &new_range);
297 if (status < 0) {
298 mutex_unlock(&chip->lock);
299 dev_err(dev, "Error in setting max range\n");
300 return status;
301 }
302 chip->range = new_range;
303 mutex_unlock(&chip->lock);
304
305 return count;
306}
307
308/* resolution */
309static ssize_t show_resolution(struct device *dev,
310 struct device_attribute *attr, char *buf)
311{
312 struct iio_dev *indio_dev = dev_get_drvdata(dev);
927afbec 313 struct isl29018_chip *chip = iio_priv(indio_dev);
94042874
RK
314
315 return sprintf(buf, "%u\n", chip->adc_bit);
316}
317
318static ssize_t store_resolution(struct device *dev,
319 struct device_attribute *attr, const char *buf, size_t count)
320{
321 struct iio_dev *indio_dev = dev_get_drvdata(dev);
927afbec 322 struct isl29018_chip *chip = iio_priv(indio_dev);
94042874
RK
323 struct i2c_client *client = chip->client;
324 int status;
325 unsigned long lval;
326 unsigned int new_adc_bit;
327
328 if (strict_strtoul(buf, 10, &lval))
329 return -EINVAL;
330 if (!(lval == 4 || lval == 8 || lval == 12 || lval == 16)) {
331 dev_err(dev, "The resolution is not supported\n");
332 return -EINVAL;
333 }
334
335 mutex_lock(&chip->lock);
336 status = isl29018_set_resolution(client, lval, &new_adc_bit);
337 if (status < 0) {
338 mutex_unlock(&chip->lock);
339 dev_err(dev, "Error in setting resolution\n");
340 return status;
341 }
342 chip->adc_bit = new_adc_bit;
343 mutex_unlock(&chip->lock);
344
345 return count;
346}
347
348/* proximity scheme */
349static ssize_t show_prox_infrared_supression(struct device *dev,
350 struct device_attribute *attr, char *buf)
351{
352 struct iio_dev *indio_dev = dev_get_drvdata(dev);
927afbec 353 struct isl29018_chip *chip = iio_priv(indio_dev);
94042874
RK
354
355 /* return the "proximity scheme" i.e. if the chip does on chip
356 infrared supression (1 means perform on chip supression) */
357 return sprintf(buf, "%d\n", chip->prox_scheme);
358}
359
360static ssize_t store_prox_infrared_supression(struct device *dev,
361 struct device_attribute *attr, const char *buf, size_t count)
362{
363 struct iio_dev *indio_dev = dev_get_drvdata(dev);
927afbec 364 struct isl29018_chip *chip = iio_priv(indio_dev);
94042874
RK
365 unsigned long lval;
366
367 if (strict_strtoul(buf, 10, &lval))
368 return -EINVAL;
369 if (!(lval == 0UL || lval == 1UL)) {
370 dev_err(dev, "The mode is not supported\n");
371 return -EINVAL;
372 }
373
374 /* get the "proximity scheme" i.e. if the chip does on chip
375 infrared supression (1 means perform on chip supression) */
376 mutex_lock(&chip->lock);
377 chip->prox_scheme = (int)lval;
378 mutex_unlock(&chip->lock);
379
380 return count;
381}
382
383/* Read lux */
384static ssize_t show_lux(struct device *dev,
385 struct device_attribute *devattr, char *buf)
386{
387 return get_sensor_data(dev, buf, COMMMAND1_OPMODE_ALS_ONCE);
388}
389
390/* Read ir */
391static ssize_t show_ir(struct device *dev,
392 struct device_attribute *devattr, char *buf)
393{
394 return get_sensor_data(dev, buf, COMMMAND1_OPMODE_IR_ONCE);
395}
396
397/* Read nearest ir */
398static ssize_t show_proxim_ir(struct device *dev,
399 struct device_attribute *devattr, char *buf)
400{
401 return get_sensor_data(dev, buf, COMMMAND1_OPMODE_PROX_ONCE);
402}
403
94042874
RK
404static IIO_DEVICE_ATTR(range, S_IRUGO | S_IWUSR, show_range, store_range, 0);
405static IIO_CONST_ATTR(range_available, "1000 4000 16000 64000");
406static IIO_CONST_ATTR(adc_resolution_available, "4 8 12 16");
407static IIO_DEVICE_ATTR(adc_resolution, S_IRUGO | S_IWUSR,
408 show_resolution, store_resolution, 0);
409static IIO_DEVICE_ATTR(proximity_on_chip_ambient_infrared_supression,
410 S_IRUGO | S_IWUSR,
411 show_prox_infrared_supression,
412 store_prox_infrared_supression, 0);
413static IIO_DEVICE_ATTR(illuminance0_input, S_IRUGO, show_lux, NULL, 0);
414static IIO_DEVICE_ATTR(intensity_infrared_raw, S_IRUGO, show_ir, NULL, 0);
415static IIO_DEVICE_ATTR(proximity_raw, S_IRUGO, show_proxim_ir, NULL, 0);
94042874
RK
416
417#define ISL29018_DEV_ATTR(name) (&iio_dev_attr_##name.dev_attr.attr)
418#define ISL29018_CONST_ATTR(name) (&iio_const_attr_##name.dev_attr.attr)
419static struct attribute *isl29018_attributes[] = {
94042874
RK
420 ISL29018_DEV_ATTR(range),
421 ISL29018_CONST_ATTR(range_available),
422 ISL29018_DEV_ATTR(adc_resolution),
423 ISL29018_CONST_ATTR(adc_resolution_available),
424 ISL29018_DEV_ATTR(proximity_on_chip_ambient_infrared_supression),
425 ISL29018_DEV_ATTR(illuminance0_input),
426 ISL29018_DEV_ATTR(intensity_infrared_raw),
427 ISL29018_DEV_ATTR(proximity_raw),
428 NULL
429};
430
431static const struct attribute_group isl29108_group = {
432 .attrs = isl29018_attributes,
433};
434
435static int isl29018_chip_init(struct i2c_client *client)
436{
437 struct isl29018_chip *chip = i2c_get_clientdata(client);
438 int status;
439 int new_adc_bit;
440 unsigned int new_range;
441
442 memset(chip->reg_cache, 0, sizeof(chip->reg_cache));
443
444 /* set defaults */
445 status = isl29018_set_range(client, chip->range, &new_range);
446 if (status < 0) {
447 dev_err(&client->dev, "Init of isl29018 fails\n");
448 return status;
449 }
450
451 status = isl29018_set_resolution(client, chip->adc_bit,
452 &new_adc_bit);
453
454 return 0;
455}
456
6fe8135f
JC
457static const struct iio_info isl29108_info = {
458 .attrs = &isl29108_group,
459 .driver_module = THIS_MODULE,
460};
461
94042874
RK
462static int __devinit isl29018_probe(struct i2c_client *client,
463 const struct i2c_device_id *id)
464{
465 struct isl29018_chip *chip;
927afbec 466 struct iio_dev *indio_dev;
94042874
RK
467 int err;
468
927afbec
JC
469 indio_dev = iio_allocate_device(sizeof(*chip));
470 if (indio_dev == NULL) {
471 dev_err(&client->dev, "iio allocation fails\n");
94042874
RK
472 err = -ENOMEM;
473 goto exit;
474 }
927afbec 475 chip = iio_priv(indio_dev);
94042874 476
927afbec 477 i2c_set_clientdata(client, indio_dev);
94042874
RK
478 chip->client = client;
479
480 mutex_init(&chip->lock);
481
482 chip->range = 1000;
483 chip->adc_bit = 16;
484
485 err = isl29018_chip_init(client);
486 if (err)
927afbec 487 goto exit_iio_free;
94042874 488
927afbec
JC
489 indio_dev->info = &isl29108_info;
490 indio_dev->name = id->name;
491 indio_dev->dev.parent = &client->dev;
492 indio_dev->modes = INDIO_DIRECT_MODE;
493 err = iio_device_register(indio_dev);
94042874
RK
494 if (err) {
495 dev_err(&client->dev, "iio registration fails\n");
496 goto exit_iio_free;
497 }
498
499 return 0;
500exit_iio_free:
927afbec 501 iio_free_device(indio_dev);
94042874
RK
502exit:
503 return err;
504}
505
506static int __devexit isl29018_remove(struct i2c_client *client)
507{
927afbec 508 struct iio_dev *indio_dev = i2c_get_clientdata(client);
94042874
RK
509
510 dev_dbg(&client->dev, "%s()\n", __func__);
927afbec 511 iio_device_unregister(indio_dev);
94042874
RK
512
513 return 0;
514}
515
516static const struct i2c_device_id isl29018_id[] = {
517 {"isl29018", 0},
518 {}
519};
520
521MODULE_DEVICE_TABLE(i2c, isl29018_id);
522
523static struct i2c_driver isl29018_driver = {
524 .class = I2C_CLASS_HWMON,
525 .driver = {
526 .name = "isl29018",
527 .owner = THIS_MODULE,
528 },
529 .probe = isl29018_probe,
530 .remove = __devexit_p(isl29018_remove),
531 .id_table = isl29018_id,
532};
533
534static int __init isl29018_init(void)
535{
536 return i2c_add_driver(&isl29018_driver);
537}
538
539static void __exit isl29018_exit(void)
540{
541 i2c_del_driver(&isl29018_driver);
542}
543
544module_init(isl29018_init);
545module_exit(isl29018_exit);
546
547MODULE_DESCRIPTION("ISL29018 Ambient Light Sensor driver");
548MODULE_LICENSE("GPL");
This page took 0.118242 seconds and 5 git commands to generate.