aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/iio/light/ltr558als.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/iio/light/ltr558als.c')
-rw-r--r--drivers/staging/iio/light/ltr558als.c883
1 files changed, 883 insertions, 0 deletions
diff --git a/drivers/staging/iio/light/ltr558als.c b/drivers/staging/iio/light/ltr558als.c
new file mode 100644
index 00000000000..01e410b191f
--- /dev/null
+++ b/drivers/staging/iio/light/ltr558als.c
@@ -0,0 +1,883 @@
1/* Lite-On LTR-558ALS Linux Driver
2 *
3 * Copyright (c) 2012, NVIDIA Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 */
10
11#include <linux/delay.h>
12#include <linux/earlysuspend.h>
13#include <linux/fs.h>
14#include <linux/i2c.h>
15#include <linux/init.h>
16#include <linux/input.h>
17#include <linux/irq.h>
18#include <linux/kernel.h>
19#include <linux/module.h>
20#include <linux/mutex.h>
21#include <linux/pm.h>
22#include <linux/wakelock.h>
23#include <linux/interrupt.h>
24#include <linux/slab.h>
25#include <asm/gpio.h>
26#include <asm/uaccess.h>
27
28#include "ltr558als.h"
29#include "../iio.h"
30
31#define DRIVER_VERSION "1.0"
32#define DEVICE_NAME "LTR_558ALS"
33
34struct ltr558_chip {
35 struct i2c_client *client;
36 struct mutex lock;
37 struct iio_dev *indio_dev;
38 int irq;
39
40 bool is_als_enable;
41 bool als_enabled_before_suspend;
42 int als_gainrange;
43 int als_persist;
44 int als_reading;
45 int als_high_thres;
46 int als_low_thres;
47
48 bool is_prox_enable;
49 bool prox_enabled_before_suspend;
50 int ps_gainrange;
51 int prox_persist;
52 int prox_reading;
53 int prox_low_thres;
54 int prox_high_thres;
55};
56
57static int ltr558_i2c_read_reg(struct i2c_client *client, u8 regnum)
58{
59 return i2c_smbus_read_byte_data(client, regnum);
60}
61
62static int ltr558_i2c_write_reg(struct i2c_client *client, u8 regnum, u8 value)
63{
64 int writeerror;
65
66 writeerror = i2c_smbus_write_byte_data(client, regnum, value);
67 if (writeerror < 0)
68 return writeerror;
69 else
70 return 0;
71}
72
73static int ltr558_ps_enable(struct i2c_client *client, int gainrange)
74{
75 int error;
76 int setgain;
77
78 switch (gainrange) {
79 case PS_RANGE4:
80 setgain = MODE_PS_ON_Gain4;
81 break;
82
83 case PS_RANGE8:
84 setgain = MODE_PS_ON_Gain8;
85 break;
86
87 case PS_RANGE16:
88 setgain = MODE_PS_ON_Gain16;
89 break;
90
91 case PS_RANGE1:
92 default:
93 setgain = MODE_PS_ON_Gain1;
94 break;
95 }
96
97 error = ltr558_i2c_write_reg(client, LTR558_PS_CONTR, setgain);
98 mdelay(WAKEUP_DELAY);
99 return error;
100}
101
102static int ltr558_ps_disable(struct i2c_client *client)
103{
104 return ltr558_i2c_write_reg(client, LTR558_PS_CONTR, MODE_PS_StdBy);
105}
106
107static int ltr558_ps_read(struct i2c_client *client)
108{
109 int psval_lo = 0, psval_hi = 0, psdata = 0;
110 psval_lo = ltr558_i2c_read_reg(client, LTR558_PS_DATA_0);
111 if (psval_lo < 0){
112 psdata = psval_lo;
113 goto out;
114 }
115
116 psval_hi = ltr558_i2c_read_reg(client, LTR558_PS_DATA_1);
117 if (psval_hi < 0){
118 psdata = psval_hi;
119 goto out;
120 }
121
122 psdata = ((psval_hi & 0x07) * 256) + psval_lo;
123out:
124 return psdata;
125}
126
127static int ltr558_als_enable(struct i2c_client *client, int gainrange)
128{
129 int error = -1;
130
131 if (gainrange == ALS_RANGE1_320)
132 error = ltr558_i2c_write_reg(client, LTR558_ALS_CONTR,
133 MODE_ALS_ON_Range1);
134 else if (gainrange == ALS_RANGE2_64K)
135 error = ltr558_i2c_write_reg(client, LTR558_ALS_CONTR,
136 MODE_ALS_ON_Range2);
137
138 mdelay(WAKEUP_DELAY);
139 return error;
140}
141
142static int ltr558_als_disable(struct i2c_client *client)
143{
144 return ltr558_i2c_write_reg(client, LTR558_ALS_CONTR, MODE_ALS_StdBy);
145}
146
147static int ltr558_als_read(struct i2c_client *client)
148{
149 int alsval_ch0_lo, alsval_ch0_hi;
150 int alsval_ch1_lo, alsval_ch1_hi;
151 unsigned int alsval_ch0 = 0, alsval_ch1 = 0;
152 int luxdata = 0, ratio = 0;
153 long ch0_coeff = 0, ch1_coeff = 0;
154
155 alsval_ch1_lo = ltr558_i2c_read_reg(client, LTR558_ALS_DATA_CH1_0);
156 alsval_ch1_hi = ltr558_i2c_read_reg(client, LTR558_ALS_DATA_CH1_1);
157 alsval_ch1 = (alsval_ch1_hi * 256) + alsval_ch1_lo;
158
159 alsval_ch0_lo = ltr558_i2c_read_reg(client, LTR558_ALS_DATA_CH0_0);
160 alsval_ch0_hi = ltr558_i2c_read_reg(client, LTR558_ALS_DATA_CH0_1);
161 alsval_ch0 = (alsval_ch0_hi * 256) + alsval_ch0_lo;
162
163 if (alsval_ch0 == 0 && alsval_ch1 == 0)
164 return 0;
165
166 /* lux formula */
167 ratio = (100 * alsval_ch1)/(alsval_ch1 + alsval_ch0);
168
169 if (ratio < 45) {
170 ch0_coeff = 17743;
171 ch1_coeff = -11059;
172 }
173 else if ((ratio >= 45) && (ratio < 64)) {
174 ch0_coeff = 37725;
175 ch1_coeff = 13363;
176 }
177 else if ((ratio >= 64) && (ratio < 85)) {
178 ch0_coeff = 16900;
179 ch1_coeff = 1690;
180 }
181 else if (ratio >= 85) {
182 ch0_coeff = 0;
183 ch1_coeff = 0;
184 }
185
186 luxdata = ((alsval_ch0 * ch0_coeff) - (alsval_ch1 * ch1_coeff))/10000;
187 return luxdata;
188}
189
190static bool ltr558_set_proxim_high_threshold(struct i2c_client *client,
191 u32 thresh)
192{
193 bool st;
194 st = ltr558_i2c_write_reg(client, LTR558_PS_THRES_UP_0,
195 thresh & 0xFF);
196 if (st)
197 st = ltr558_i2c_write_reg(client, LTR558_PS_THRES_UP_1,
198 (thresh >> 8) & 0x07);
199 return st;
200}
201
202static bool ltr558_set_proxim_low_threshold(struct i2c_client *client,
203 u32 thresh)
204{
205 bool st;
206 st = ltr558_i2c_write_reg(client, LTR558_PS_THRES_LOW_0,
207 thresh & 0xFF);
208 if (st)
209 st = ltr558_i2c_write_reg(client, LTR558_PS_THRES_LOW_1,
210 (thresh >> 8) & 0x07);
211 return st;
212}
213
214static bool ltr558_set_als_high_threshold(struct i2c_client *client, u32 thresh)
215{
216 bool st;
217 st = ltr558_i2c_write_reg(client, LTR558_ALS_THRES_UP_0,
218 thresh & 0xFF);
219 if (st)
220 st = ltr558_i2c_write_reg(client, LTR558_ALS_THRES_UP_1,
221 (thresh >> 8) & 0xFF);
222 return st;
223}
224
225static bool ltr558_set_als_low_threshold(struct i2c_client *client, u32 thresh)
226{
227 bool st;
228 st = ltr558_i2c_write_reg(client, LTR558_ALS_THRES_LOW_0,
229 thresh & 0xFF);
230 if (st)
231 st = ltr558_i2c_write_reg(client, LTR558_ALS_THRES_LOW_1,
232 ((thresh >> 8) & 0xFF));
233 return st;
234}
235
236/* Sysfs interface */
237
238/* proximity enable/disable */
239static ssize_t show_prox_enable(struct device *dev,
240 struct device_attribute *attr, char *buf)
241{
242 struct iio_dev *indio_dev = dev_get_drvdata(dev);
243 struct ltr558_chip *chip = indio_dev->dev_data;
244
245 dev_vdbg(dev, "%s()\n", __func__);
246 if (chip->is_prox_enable)
247 return sprintf(buf, "1\n");
248 else
249 return sprintf(buf, "0\n");
250}
251
252static ssize_t store_prox_enable(struct device *dev,
253 struct device_attribute *attr, const char *buf, size_t count)
254{
255 struct iio_dev *indio_dev = dev_get_drvdata(dev);
256 struct ltr558_chip *chip = indio_dev->dev_data;
257 struct i2c_client *client = chip->client;
258 int err = 0;
259 unsigned long lval;
260
261 dev_vdbg(dev, "%s()\n", __func__);
262
263 if (strict_strtoul(buf, 10, &lval))
264 return -EINVAL;
265 if ((lval != 1) && (lval != 0)) {
266 dev_err(dev, "illegal value %lu\n", lval);
267 return -EINVAL;
268 }
269
270 mutex_lock(&chip->lock);
271 if (lval == 1)
272 err = ltr558_ps_enable(client, PS_RANGE1);
273 else
274 err = ltr558_ps_disable(client);
275
276 if (err < 0)
277 dev_err(dev, "Error in enabling proximity\n");
278 else
279 chip->is_prox_enable = (lval) ? true : false;
280
281 mutex_unlock(&chip->lock);
282 return count;
283}
284
285/* Proximity low thresholds */
286static ssize_t show_proxim_low_threshold(struct device *dev,
287 struct device_attribute *attr, char *buf)
288{
289 struct iio_dev *indio_dev = dev_get_drvdata(dev);
290 struct ltr558_chip *chip = indio_dev->dev_data;
291
292 dev_vdbg(dev, "%s()\n", __func__);
293 return sprintf(buf, "%d\n", chip->prox_low_thres);
294}
295
296static ssize_t store_proxim_low_threshold(struct device *dev,
297 struct device_attribute *attr, const char *buf, size_t count)
298{
299 struct iio_dev *indio_dev = dev_get_drvdata(dev);
300 struct ltr558_chip *chip = indio_dev->dev_data;
301 struct i2c_client *client = chip->client;
302 bool st;
303 unsigned long lval;
304
305 dev_vdbg(dev, "%s()\n", __func__);
306
307 if (strict_strtoul(buf, 10, &lval))
308 return -EINVAL;
309
310 if ((lval > 0x7FF) || (lval < 0x0)) {
311 dev_err(dev, "The threshold is not supported\n");
312 return -EINVAL;
313 }
314
315 mutex_lock(&chip->lock);
316 st = ltr558_set_proxim_low_threshold(client, (u8)lval);
317 if (st)
318 chip->prox_low_thres = (int)lval;
319 else
320 dev_err(dev, "Error in setting proximity low threshold\n");
321
322 mutex_unlock(&chip->lock);
323 return count;
324}
325
326/* Proximity high thresholds */
327static ssize_t show_proxim_high_threshold(struct device *dev,
328 struct device_attribute *attr, char *buf)
329{
330 struct iio_dev *indio_dev = dev_get_drvdata(dev);
331 struct ltr558_chip *chip = indio_dev->dev_data;
332
333 dev_vdbg(dev, "%s()\n", __func__);
334 return sprintf(buf, "%d\n", chip->prox_high_thres);
335}
336
337static ssize_t store_proxim_high_threshold(struct device *dev,
338 struct device_attribute *attr, const char *buf, size_t count)
339{
340 struct iio_dev *indio_dev = dev_get_drvdata(dev);
341 struct ltr558_chip *chip = indio_dev->dev_data;
342 struct i2c_client *client = chip->client;
343 bool st;
344 unsigned long lval;
345
346 dev_vdbg(dev, "%s()\n", __func__);
347
348 if (strict_strtoul(buf, 10, &lval))
349 return -EINVAL;
350
351 if ((lval > 0x7FF) || (lval < 0x0)) {
352 dev_err(dev, "The threshold is not supported\n");
353 return -EINVAL;
354 }
355
356 mutex_lock(&chip->lock);
357 st = ltr558_set_proxim_high_threshold(client, lval);
358 if (st)
359 chip->prox_high_thres = (int)lval;
360 else
361 dev_err(dev, "Error in setting proximity high threshold\n");
362
363 mutex_unlock(&chip->lock);
364 return count;
365}
366
367/* als enable/disable */
368static ssize_t show_als_enable(struct device *dev,
369 struct device_attribute *attr, char *buf)
370{
371 struct iio_dev *indio_dev = dev_get_drvdata(dev);
372 struct ltr558_chip *chip = indio_dev->dev_data;
373
374 dev_vdbg(dev, "%s()\n", __func__);
375 if (chip->is_als_enable)
376 return sprintf(buf, "1\n");
377 else
378 return sprintf(buf, "0\n");
379}
380
381static ssize_t store_als_enable(struct device *dev,
382 struct device_attribute *attr, const char *buf, size_t count)
383{
384 struct iio_dev *indio_dev = dev_get_drvdata(dev);
385 struct ltr558_chip *chip = indio_dev->dev_data;
386 struct i2c_client *client = chip->client;
387 int err = 0;
388 unsigned long lval;
389
390 dev_vdbg(dev, "%s()\n", __func__);
391
392 if (strict_strtoul(buf, 10, &lval))
393 return -EINVAL;
394 if ((lval != 1) && (lval != 0)) {
395 dev_err(dev, "illegal value %lu\n", lval);
396 return -EINVAL;
397 }
398
399 mutex_lock(&chip->lock);
400 if (lval == 1)
401 err = ltr558_als_enable(client, chip->als_gainrange);
402 else
403 err = ltr558_als_disable(client);
404
405 if (err < 0)
406 dev_err(dev, "Error in enabling ALS\n");
407 else
408 chip->is_als_enable = (lval) ? true : false;
409
410 mutex_unlock(&chip->lock);
411 return count;
412}
413
414/* als low thresholds */
415static ssize_t show_als_low_threshold(struct device *dev,
416 struct device_attribute *attr, char *buf)
417{
418 struct iio_dev *indio_dev = dev_get_drvdata(dev);
419 struct ltr558_chip *chip = indio_dev->dev_data;
420
421 dev_vdbg(dev, "%s()\n", __func__);
422 return sprintf(buf, "%d\n", chip->als_low_thres);
423}
424
425static ssize_t store_als_low_threshold(struct device *dev,
426 struct device_attribute *attr, const char *buf, size_t count)
427{
428 struct iio_dev *indio_dev = dev_get_drvdata(dev);
429 struct ltr558_chip *chip = indio_dev->dev_data;
430 struct i2c_client *client = chip->client;
431 bool st;
432 unsigned long lval;
433
434 dev_vdbg(dev, "%s()\n", __func__);
435
436 if (strict_strtoul(buf, 10, &lval))
437 return -EINVAL;
438
439 if ((lval > 0xFFFF) || (lval < 0x0)) {
440 dev_err(dev, "The ALS threshold is not supported\n");
441 return -EINVAL;
442 }
443
444 mutex_lock(&chip->lock);
445 st = ltr558_set_als_low_threshold(client, (int)lval);
446 if (st)
447 chip->als_low_thres = (int)lval;
448 else
449 dev_err(dev, "Error in setting als low threshold\n");
450 mutex_unlock(&chip->lock);
451 return count;
452}
453
454/* Als high thresholds */
455static ssize_t show_als_high_threshold(struct device *dev,
456 struct device_attribute *attr, char *buf)
457{
458 struct iio_dev *indio_dev = dev_get_drvdata(dev);
459 struct ltr558_chip *chip = indio_dev->dev_data;
460
461 dev_vdbg(dev, "%s()\n", __func__);
462 return sprintf(buf, "%d\n", chip->als_high_thres);
463}
464
465static ssize_t store_als_high_threshold(struct device *dev,
466 struct device_attribute *attr, const char *buf, size_t count)
467{
468 struct iio_dev *indio_dev = dev_get_drvdata(dev);
469 struct ltr558_chip *chip = indio_dev->dev_data;
470 struct i2c_client *client = chip->client;
471 bool st;
472 unsigned long lval;
473
474 dev_vdbg(dev, "%s()\n", __func__);
475
476 if (strict_strtoul(buf, 10, &lval))
477 return -EINVAL;
478
479 if ((lval > 0xFFFF) || (lval < 0x0)) {
480 dev_err(dev, "The als threshold is not supported\n");
481 return -EINVAL;
482 }
483
484 mutex_lock(&chip->lock);
485 st = ltr558_set_als_high_threshold(client, (int)lval);
486 if (st)
487 chip->als_high_thres = (int)lval;
488 else
489 dev_err(dev, "Error in setting als high threshold\n");
490 mutex_unlock(&chip->lock);
491 return count;
492}
493
494/* Proximity persist */
495static ssize_t show_proxim_persist(struct device *dev,
496 struct device_attribute *attr, char *buf)
497{
498 struct iio_dev *indio_dev = dev_get_drvdata(dev);
499 struct ltr558_chip *chip = indio_dev->dev_data;
500
501 dev_vdbg(dev, "%s()\n", __func__);
502 return sprintf(buf, "%d\n", chip->prox_persist);
503}
504
505static ssize_t store_proxim_persist(struct device *dev,
506 struct device_attribute *attr, const char *buf, size_t count)
507{
508 struct iio_dev *indio_dev = dev_get_drvdata(dev);
509 struct ltr558_chip *chip = indio_dev->dev_data;
510 unsigned long lval;
511
512 dev_vdbg(dev, "%s()\n", __func__);
513
514 if (strict_strtoul(buf, 10, &lval))
515 return -EINVAL;
516
517 if ((lval > 16) || (lval < 0x0)) {
518 dev_err(dev, "The proximity persist is not supported\n");
519 return -EINVAL;
520 }
521
522 mutex_lock(&chip->lock);
523 chip->prox_persist = (int)lval;
524 mutex_unlock(&chip->lock);
525 return count;
526}
527
528/* als/ir persist */
529static ssize_t show_als_persist(struct device *dev,
530 struct device_attribute *attr, char *buf)
531{
532 struct iio_dev *indio_dev = dev_get_drvdata(dev);
533 struct ltr558_chip *chip = indio_dev->dev_data;
534
535 dev_vdbg(dev, "%s()\n", __func__);
536 return sprintf(buf, "%d\n", chip->als_persist);
537}
538
539static ssize_t store_als_persist(struct device *dev,
540 struct device_attribute *attr, const char *buf, size_t count)
541{
542 struct iio_dev *indio_dev = dev_get_drvdata(dev);
543 struct ltr558_chip *chip = indio_dev->dev_data;
544 unsigned long lval;
545
546 dev_vdbg(dev, "%s()\n", __func__);
547
548 if (strict_strtoul(buf, 10, &lval))
549 return -EINVAL;
550
551 if ((lval > 16) || (lval < 0x0)) {
552 dev_err(dev, "The als persist is not supported\n");
553 return -EINVAL;
554 }
555
556 mutex_lock(&chip->lock);
557 chip->als_persist = (int)lval;
558 mutex_unlock(&chip->lock);
559 return count;
560}
561
562/* Display proxim data */
563static ssize_t show_proxim_data(struct device *dev,
564 struct device_attribute *attr, char *buf)
565{
566 struct iio_dev *indio_dev = dev_get_drvdata(dev);
567 struct ltr558_chip *chip = indio_dev->dev_data;
568 int prox_data = 0;
569 ssize_t buf_count = 0;
570
571 dev_vdbg(dev, "%s()\n", __func__);
572 mutex_lock(&chip->lock);
573
574 if (chip->is_prox_enable) {
575 prox_data = ltr558_ps_read(chip->client);
576 chip->prox_reading = prox_data;
577 buf_count = sprintf(buf, "%d\n", prox_data);
578 }
579 else
580 buf_count = sprintf(buf, "%d\n", chip->prox_reading);
581 mutex_unlock(&chip->lock);
582 return buf_count;
583}
584
585/* Display als data */
586static ssize_t show_als_data(struct device *dev,
587 struct device_attribute *attr, char *buf)
588{
589 struct iio_dev *indio_dev = dev_get_drvdata(dev);
590 struct ltr558_chip *chip = indio_dev->dev_data;
591 ssize_t buf_count = 0;
592 int als_data = 0;
593
594 dev_vdbg(dev, "%s()\n", __func__);
595
596 mutex_lock(&chip->lock);
597 if (chip->is_als_enable) {
598 als_data = ltr558_als_read(chip->client);
599 buf_count = sprintf(buf, "%d\n", als_data);
600 chip->als_reading = als_data;
601 }
602 else
603 buf_count = sprintf(buf, "%d\n", chip->als_reading);
604 mutex_unlock(&chip->lock);
605
606 return buf_count;
607}
608
609/* Read name */
610static ssize_t show_name(struct device *dev,
611 struct device_attribute *attr, char *buf)
612{
613 struct iio_dev *indio_dev = dev_get_drvdata(dev);
614 struct ltr558_chip *chip = indio_dev->dev_data;
615 return sprintf(buf, "%s\n", chip->client->name);
616}
617
618static IIO_DEVICE_ATTR(proximity_low_threshold, S_IRUGO | S_IWUSR,
619 show_proxim_low_threshold, store_proxim_low_threshold, 0);
620static IIO_DEVICE_ATTR(proximity_high_threshold, S_IRUGO | S_IWUSR,
621 show_proxim_high_threshold, store_proxim_high_threshold, 0);
622static IIO_DEVICE_ATTR(proximity_persist, S_IRUGO | S_IWUSR,
623 show_proxim_persist, store_proxim_persist, 0);
624static IIO_DEVICE_ATTR(proximity_enable, S_IRUGO | S_IWUSR,
625 show_prox_enable, store_prox_enable, 0);
626static IIO_DEVICE_ATTR(proximity_value, S_IRUGO,
627 show_proxim_data, NULL, 0);
628
629static IIO_DEVICE_ATTR(als_low_threshold, S_IRUGO | S_IWUSR,
630 show_als_low_threshold, store_als_low_threshold, 0);
631static IIO_DEVICE_ATTR(als_high_threshold, S_IRUGO | S_IWUSR,
632 show_als_high_threshold, store_als_high_threshold, 0);
633static IIO_DEVICE_ATTR(als_persist, S_IRUGO | S_IWUSR,
634 show_als_persist, store_als_persist, 0);
635static IIO_DEVICE_ATTR(als_enable, S_IRUGO | S_IWUSR,
636 show_als_enable, store_als_enable, 0);
637static IIO_DEVICE_ATTR(als_value, S_IRUGO,
638 show_als_data, NULL, 0);
639
640static IIO_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0);
641
642static struct attribute *ltr558_attributes[] = {
643 &iio_dev_attr_name.dev_attr.attr,
644
645 &iio_dev_attr_als_low_threshold.dev_attr.attr,
646 &iio_dev_attr_als_high_threshold.dev_attr.attr,
647 &iio_dev_attr_als_enable.dev_attr.attr,
648 &iio_dev_attr_als_persist.dev_attr.attr,
649 &iio_dev_attr_als_value.dev_attr.attr,
650
651 &iio_dev_attr_proximity_low_threshold.dev_attr.attr,
652 &iio_dev_attr_proximity_high_threshold.dev_attr.attr,
653 &iio_dev_attr_proximity_enable.dev_attr.attr,
654 &iio_dev_attr_proximity_persist.dev_attr.attr,
655 &iio_dev_attr_proximity_value.dev_attr.attr,
656 NULL
657};
658
659static const struct attribute_group ltr558_group = {
660 .attrs = ltr558_attributes,
661};
662
663static int ltr558_chip_init(struct i2c_client *client)
664{
665 struct ltr558_chip *chip = i2c_get_clientdata(client);
666 int error = 0;
667
668 mdelay(PON_DELAY);
669
670 chip->is_prox_enable = 0;
671 chip->prox_low_thres = 0;
672 chip->prox_high_thres = 0x7FF;
673 chip->prox_reading = 0;
674
675 chip->als_low_thres = 0;
676 chip->als_high_thres = 0xFFFF;
677 chip->als_reading = 0;
678
679 chip->is_als_enable = 0;
680 chip->prox_persist = 0;
681 chip->als_persist = 0;
682
683 /* Enable PS to Gain1 at startup */
684 chip->ps_gainrange = PS_RANGE1;
685 error = ltr558_ps_enable(client, chip->ps_gainrange);
686 if (error < 0)
687 goto out;
688
689
690 /* Enable ALS to Full Range at startup */
691 chip->als_gainrange = ALS_RANGE2_64K;
692 error = ltr558_als_enable(client, chip->als_gainrange);
693 if (error < 0)
694 goto out;
695
696out:
697 return error;
698}
699
700static const struct iio_info ltr558_info = {
701 .attrs = &ltr558_group,
702 .driver_module = THIS_MODULE,
703};
704
705static irqreturn_t threshold_isr(int irq, void *irq_data)
706{
707 struct ltr558_chip *chip = (struct ltr558_chip *)irq_data;
708 s32 int_reg;
709 struct i2c_client *client = chip->client;
710
711 int_reg = i2c_smbus_read_byte_data(client, LTR558_ALS_PS_STATUS);
712 if (int_reg < 0) {
713 dev_err(&client->dev, "Error in reading register %d, error %d\n",
714 LTR558_ALS_PS_STATUS, int_reg);
715 return IRQ_HANDLED;
716 }
717
718 if (int_reg & STATUS_ALS_INT_TRIGGER) {
719 if (int_reg & STATUS_ALS_NEW_DATA)
720 chip->als_reading = ltr558_als_read(client);
721 }
722
723 if (int_reg & STATUS_PS_INT_TRIGGER) {
724 if (int_reg & STATUS_PS_NEW_DATA)
725 chip->prox_reading = ltr558_ps_read(client);
726 }
727
728 return IRQ_HANDLED;
729}
730
731static int ltr558_probe(struct i2c_client *client,
732 const struct i2c_device_id *id)
733{
734 int ret = 0;
735 struct ltr558_chip *chip;
736
737 /* data memory allocation */
738 chip = kzalloc(sizeof(struct ltr558_chip), GFP_KERNEL);
739 if (chip == NULL) {
740 printk(KERN_ALERT "%s: LTR-558ALS kzalloc failed.\n", __func__);
741 ret = -ENOMEM;
742 goto exit;
743 }
744
745 i2c_set_clientdata(client, chip);
746 chip->client = client;
747 chip->irq = client->irq;
748
749 if (chip->irq > 0) {
750 ret = request_threaded_irq(chip->irq, NULL, threshold_isr,
751 IRQF_SHARED, "LTR558_ALS", chip);
752 if (ret) {
753 dev_err(&client->dev, "Unable to register irq %d; "
754 "ret %d\n", chip->irq, ret);
755 goto exit_free;
756 }
757 }
758
759 mutex_init(&chip->lock);
760
761 ret = ltr558_chip_init(client);
762 if (ret)
763 goto exit_free;
764
765 chip->indio_dev = iio_allocate_device(0);
766 if (!chip->indio_dev) {
767 dev_err(&client->dev, "iio allocation fails\n");
768 goto exit_irq;
769 }
770
771 chip->indio_dev->info = &ltr558_info;
772 chip->indio_dev->dev.parent = &client->dev;
773 chip->indio_dev->dev_data = (void *)(chip);
774 chip->indio_dev->modes = INDIO_DIRECT_MODE;
775 ret = iio_device_register(chip->indio_dev);
776 if (ret) {
777 dev_err(&client->dev, "iio registration fails\n");
778 goto exit_iio_free;
779 }
780
781 dev_dbg(&client->dev, "%s() success\n", __func__);
782 return 0;
783
784exit_iio_free:
785 iio_free_device(chip->indio_dev);
786exit_irq:
787 if (chip->irq > 0)
788 free_irq(chip->irq, chip);
789exit_free:
790 kfree(chip);
791exit:
792 return ret;
793}
794
795
796static int ltr558_remove(struct i2c_client *client)
797{
798 struct ltr558_chip *chip = i2c_get_clientdata(client);
799
800 dev_dbg(&client->dev, "%s()\n", __func__);
801 iio_device_unregister(chip->indio_dev);
802 if (chip->irq > 0)
803 free_irq(chip->irq, chip);
804 ltr558_ps_disable(client);
805 ltr558_als_disable(client);
806 kfree(chip);
807 return 0;
808}
809
810
811static int ltr558_suspend(struct i2c_client *client, pm_message_t mesg)
812{
813 struct ltr558_chip *chip = i2c_get_clientdata(client);
814 int ret;
815
816 if (chip->is_als_enable == 1)
817 chip->als_enabled_before_suspend = 1;
818 if (chip->is_prox_enable == 1)
819 chip->prox_enabled_before_suspend = 1;
820
821 ret = ltr558_ps_disable(client);
822 if (ret == 0)
823 ret = ltr558_als_disable(client);
824
825 return ret;
826}
827
828
829static int ltr558_resume(struct i2c_client *client)
830{
831 struct ltr558_chip *chip = i2c_get_clientdata(client);
832 int error = 0;
833
834 mdelay(PON_DELAY);
835
836 if (chip->prox_enabled_before_suspend == 1) {
837 error = ltr558_ps_enable(client, chip->ps_gainrange);
838 if (error < 0)
839 goto out;
840 }
841
842 if (chip->als_enabled_before_suspend == 1) {
843 error = ltr558_als_enable(client, chip->als_gainrange);
844 }
845out:
846 return error;
847}
848
849
850static const struct i2c_device_id ltr558_id[] = {
851 { DEVICE_NAME, 0 },
852 {}
853};
854
855
856static struct i2c_driver ltr558_driver = {
857 .class = I2C_CLASS_HWMON,
858 .probe = ltr558_probe,
859 .remove = ltr558_remove,
860 .id_table = ltr558_id,
861 .driver = {
862 .owner = THIS_MODULE,
863 .name = DEVICE_NAME,
864 },
865 .suspend = ltr558_suspend,
866 .resume = ltr558_resume,
867};
868
869
870static int __init ltr558_driverinit(void)
871{
872 return i2c_add_driver(&ltr558_driver);
873}
874
875
876static void __exit ltr558_driverexit(void)
877{
878 i2c_del_driver(&ltr558_driver);
879}
880
881
882module_init(ltr558_driverinit)
883module_exit(ltr558_driverexit)