aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAmit Kucheria <amit.kucheria@verdurent.com>2009-11-09 08:14:28 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2009-12-11 15:23:19 -0500
commitee1f1fa4071416b130fd0771d1f26ea3f41e1fc3 (patch)
treed99055300b4b7aa812256396262de67ab0e0bc8d
parent51bf00aef02d410bf74afb31ec2d5dbcedb1a52f (diff)
Staging: iio: tsl2563 ambient light sensor driver
Add driver support for the tsl2563 TAOS ambient light sensor. After looking at discussions on LKML, the driver was modified from a 'hwmon' driver to an 'iio' driver. The sysfs interfaces have been tested on an RX51 (N900) to see if it responds to changing light conditions. The only real reason for submitting this to staging is that it is dependent on the IIO subsystem. Signed-off-by: Amit Kucheria <amit.kucheria@verdurent.com> Cc: Jonathan Cameron <jic23@cam.ac.uk> Cc: linux-omap@vger.kernel.org Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/staging/iio/light/Kconfig11
-rw-r--r--drivers/staging/iio/light/Makefile1
-rw-r--r--drivers/staging/iio/light/tsl2563.c772
-rw-r--r--drivers/staging/iio/light/tsl2563.h9
4 files changed, 793 insertions, 0 deletions
diff --git a/drivers/staging/iio/light/Kconfig b/drivers/staging/iio/light/Kconfig
index 12af0c46fe22..cf0d0d64b958 100644
--- a/drivers/staging/iio/light/Kconfig
+++ b/drivers/staging/iio/light/Kconfig
@@ -11,3 +11,14 @@ config TSL2561
11 convertor. This chip has two light sensors. One is broadband 11 convertor. This chip has two light sensors. One is broadband
12 including infrared whilst the other measures only infrared. 12 including infrared whilst the other measures only infrared.
13 Provides direct access via sysfs. 13 Provides direct access via sysfs.
14
15config SENSORS_TSL2563
16 tristate "TAOS TSL2563 ambient light sensor"
17 depends on I2C
18 help
19 If you say yes here you get support for the Taos TSL2563
20 ambient light sensor (found in N900).
21
22 This driver can also be built as a module. If so, the module
23 will be called tsl2563.
24
diff --git a/drivers/staging/iio/light/Makefile b/drivers/staging/iio/light/Makefile
index ccff15167609..30dbfb1033a3 100644
--- a/drivers/staging/iio/light/Makefile
+++ b/drivers/staging/iio/light/Makefile
@@ -3,3 +3,4 @@
3# 3#
4 4
5obj-$(CONFIG_TSL2561) += tsl2561.o 5obj-$(CONFIG_TSL2561) += tsl2561.o
6obj-$(CONFIG_SENSORS_TSL2563) += tsl2563.o
diff --git a/drivers/staging/iio/light/tsl2563.c b/drivers/staging/iio/light/tsl2563.c
new file mode 100644
index 000000000000..3e812b2d0cd4
--- /dev/null
+++ b/drivers/staging/iio/light/tsl2563.c
@@ -0,0 +1,772 @@
1/*
2 * drivers/i2c/chips/tsl2563.c
3 *
4 * Copyright (C) 2008 Nokia Corporation
5 *
6 * Written by Timo O. Karjalainen <timo.o.karjalainen@nokia.com>
7 * Contact: Amit Kucheria <amit.kucheria@verdurent.com>
8 *
9 * Converted to IIO driver
10 * Amit Kucheria <amit.kucheria@verdurent.com>
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * version 2 as published by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
24 * 02110-1301 USA
25 */
26
27#include <linux/module.h>
28#include <linux/i2c.h>
29#include <linux/interrupt.h>
30#include <linux/sched.h>
31#include <linux/mutex.h>
32#include <linux/delay.h>
33#include <linux/platform_device.h>
34#include <linux/pm.h>
35#include <linux/hwmon.h>
36#include <linux/err.h>
37
38#include "../iio.h"
39#include "tsl2563.h"
40
41#define DRIVER_NAME "tsl2563"
42
43/* Use this many bits for fraction part. */
44#define ADC_FRAC_BITS (14)
45
46/* Given number of 1/10000's in ADC_FRAC_BITS precision. */
47#define FRAC10K(f) (((f) * (1L << (ADC_FRAC_BITS))) / (10000))
48
49/* Bits used for fraction in calibration coefficients.*/
50#define CALIB_FRAC_BITS (10)
51/* 0.5 in CALIB_FRAC_BITS precision */
52#define CALIB_FRAC_HALF (1 << (CALIB_FRAC_BITS - 1))
53/* Make a fraction from a number n that was multiplied with b. */
54#define CALIB_FRAC(n, b) (((n) << CALIB_FRAC_BITS) / (b))
55/* Decimal 10^(digits in sysfs presentation) */
56#define CALIB_BASE_SYSFS (1000)
57
58#define TSL2563_CMD (0x80)
59#define TSL2563_CLEARINT (0x40)
60
61#define TSL2563_REG_CTRL (0x00)
62#define TSL2563_REG_TIMING (0x01)
63#define TSL2563_REG_LOWLOW (0x02) /* data0 low threshold, 2 bytes */
64#define TSL2563_REG_LOWHIGH (0x03)
65#define TSL2563_REG_HIGHLOW (0x04) /* data0 high threshold, 2 bytes */
66#define TSL2563_REG_HIGHHIGH (0x05)
67#define TSL2563_REG_INT (0x06)
68#define TSL2563_REG_ID (0x0a)
69#define TSL2563_REG_DATA0LOW (0x0c) /* broadband sensor value, 2 bytes */
70#define TSL2563_REG_DATA0HIGH (0x0d)
71#define TSL2563_REG_DATA1LOW (0x0e) /* infrared sensor value, 2 bytes */
72#define TSL2563_REG_DATA1HIGH (0x0f)
73
74#define TSL2563_CMD_POWER_ON (0x03)
75#define TSL2563_CMD_POWER_OFF (0x00)
76#define TSL2563_CTRL_POWER_MASK (0x03)
77
78#define TSL2563_TIMING_13MS (0x00)
79#define TSL2563_TIMING_100MS (0x01)
80#define TSL2563_TIMING_400MS (0x02)
81#define TSL2563_TIMING_MASK (0x03)
82#define TSL2563_TIMING_GAIN16 (0x10)
83#define TSL2563_TIMING_GAIN1 (0x00)
84
85#define TSL2563_INT_DISBLED (0x00)
86#define TSL2563_INT_LEVEL (0x10)
87#define TSL2563_INT_PERSIST(n) ((n) & 0x0F)
88
89struct tsl2563_gainlevel_coeff {
90 u8 gaintime;
91 u16 min;
92 u16 max;
93};
94
95static struct tsl2563_gainlevel_coeff tsl2563_gainlevel_table[] = {
96 {
97 .gaintime = TSL2563_TIMING_400MS | TSL2563_TIMING_GAIN16,
98 .min = 0,
99 .max = 65534,
100 }, {
101 .gaintime = TSL2563_TIMING_400MS | TSL2563_TIMING_GAIN1,
102 .min = 2048,
103 .max = 65534,
104 }, {
105 .gaintime = TSL2563_TIMING_100MS | TSL2563_TIMING_GAIN1,
106 .min = 4095,
107 .max = 37177,
108 }, {
109 .gaintime = TSL2563_TIMING_13MS | TSL2563_TIMING_GAIN1,
110 .min = 3000,
111 .max = 65535,
112 },
113};
114
115struct tsl2563_chip {
116 struct mutex lock;
117 struct i2c_client *client;
118 struct iio_dev *indio_dev;
119 struct delayed_work poweroff_work;
120
121 /* Remember state for suspend and resume functions */
122 pm_message_t state;
123
124 struct tsl2563_gainlevel_coeff *gainlevel;
125
126 /* Thresholds are in lux */
127 u16 low_thres;
128 u16 high_thres;
129 u8 intr;
130
131 /* Calibration coefficients */
132 u32 calib0;
133 u32 calib1;
134 int cover_comp_gain;
135
136 /* Cache current values, to be returned while suspended */
137 u32 data0;
138 u32 data1;
139};
140
141static int tsl2563_write(struct i2c_client *client, u8 reg, u8 value)
142{
143 int ret;
144 u8 buf[2];
145
146 buf[0] = TSL2563_CMD | reg;
147 buf[1] = value;
148
149 ret = i2c_master_send(client, buf, sizeof(buf));
150 return (ret == sizeof(buf)) ? 0 : ret;
151}
152
153static int tsl2563_read(struct i2c_client *client, u8 reg, void *buf, int len)
154{
155 int ret;
156 u8 cmd = TSL2563_CMD | reg;
157
158 ret = i2c_master_send(client, &cmd, sizeof(cmd));
159 if (ret != sizeof(cmd))
160 return ret;
161
162 return i2c_master_recv(client, buf, len);
163}
164
165static int tsl2563_set_power(struct tsl2563_chip *chip, int on)
166{
167 struct i2c_client *client = chip->client;
168 u8 cmd;
169
170 cmd = on ? TSL2563_CMD_POWER_ON : TSL2563_CMD_POWER_OFF;
171 return tsl2563_write(client, TSL2563_REG_CTRL, cmd);
172}
173
174/*
175 * Return value is 0 for off, 1 for on, or a negative error
176 * code if reading failed.
177 */
178static int tsl2563_get_power(struct tsl2563_chip *chip)
179{
180 struct i2c_client *client = chip->client;
181 int ret;
182 u8 val;
183
184 ret = tsl2563_read(client, TSL2563_REG_CTRL, &val, sizeof(val));
185 if (ret != sizeof(val))
186 return ret;
187
188 return (val & TSL2563_CTRL_POWER_MASK) == TSL2563_CMD_POWER_ON;
189}
190
191static int tsl2563_configure(struct tsl2563_chip *chip)
192{
193 struct i2c_client *client = chip->client;
194 int ret;
195
196 ret = tsl2563_write(client, TSL2563_REG_TIMING,
197 chip->gainlevel->gaintime);
198 if (ret)
199 goto out;
200
201 ret = tsl2563_write(client, TSL2563_REG_INT, chip->intr);
202
203out:
204 return ret;
205}
206
207static void tsl2563_poweroff_work(struct work_struct *work)
208{
209 struct tsl2563_chip *chip =
210 container_of(work, struct tsl2563_chip, poweroff_work.work);
211 tsl2563_set_power(chip, 0);
212}
213
214static int tsl2563_detect(struct tsl2563_chip *chip)
215{
216 int ret;
217
218 ret = tsl2563_set_power(chip, 1);
219 if (ret)
220 return ret;
221
222 ret = tsl2563_get_power(chip);
223 if (ret < 0)
224 return ret;
225
226 return ret ? 0 : -ENODEV;
227}
228
229static int tsl2563_read_id(struct tsl2563_chip *chip, u8 *id)
230{
231 struct i2c_client *client = chip->client;
232 int ret;
233
234 ret = tsl2563_read(client, TSL2563_REG_ID, id, sizeof(*id));
235 if (ret != sizeof(*id))
236 return ret;
237
238 return 0;
239}
240
241/*
242 * "Normalized" ADC value is one obtained with 400ms of integration time and
243 * 16x gain. This function returns the number of bits of shift needed to
244 * convert between normalized values and HW values obtained using given
245 * timing and gain settings.
246 */
247static int adc_shiftbits(u8 timing)
248{
249 int shift = 0;
250
251 switch (timing & TSL2563_TIMING_MASK) {
252 case TSL2563_TIMING_13MS:
253 shift += 5;
254 break;
255 case TSL2563_TIMING_100MS:
256 shift += 2;
257 break;
258 case TSL2563_TIMING_400MS:
259 /* no-op */
260 break;
261 }
262
263 if (!(timing & TSL2563_TIMING_GAIN16))
264 shift += 4;
265
266 return shift;
267}
268
269/* Convert a HW ADC value to normalized scale. */
270static u32 normalize_adc(u16 adc, u8 timing)
271{
272 return adc << adc_shiftbits(timing);
273}
274
275static void tsl2563_wait_adc(struct tsl2563_chip *chip)
276{
277 unsigned int delay;
278
279 switch (chip->gainlevel->gaintime & TSL2563_TIMING_MASK) {
280 case TSL2563_TIMING_13MS:
281 delay = 14;
282 break;
283 case TSL2563_TIMING_100MS:
284 delay = 101;
285 break;
286 default:
287 delay = 402;
288 }
289 /*
290 * TODO: Make sure that we wait at least required delay but why we
291 * have to extend it one tick more?
292 */
293 schedule_timeout_interruptible(msecs_to_jiffies(delay) + 2);
294}
295
296static int tsl2563_adjust_gainlevel(struct tsl2563_chip *chip, u16 adc)
297{
298 struct i2c_client *client = chip->client;
299
300 if (adc > chip->gainlevel->max || adc < chip->gainlevel->min) {
301
302 (adc > chip->gainlevel->max) ?
303 chip->gainlevel++ : chip->gainlevel--;
304
305 tsl2563_write(client, TSL2563_REG_TIMING,
306 chip->gainlevel->gaintime);
307
308 tsl2563_wait_adc(chip);
309 tsl2563_wait_adc(chip);
310
311 return 1;
312 } else
313 return 0;
314}
315
316static int tsl2563_get_adc(struct tsl2563_chip *chip)
317{
318 struct i2c_client *client = chip->client;
319 u8 buf0[2], buf1[2];
320 u16 adc0, adc1;
321 int retry = 1;
322 int ret = 0;
323
324 if (chip->state.event != PM_EVENT_ON)
325 goto out;
326
327 cancel_delayed_work(&chip->poweroff_work);
328
329 if (!tsl2563_get_power(chip)) {
330 ret = tsl2563_set_power(chip, 1);
331 if (ret)
332 goto out;
333 ret = tsl2563_configure(chip);
334 if (ret)
335 goto out;
336 tsl2563_wait_adc(chip);
337 }
338
339 while (retry) {
340 ret = tsl2563_read(client,
341 TSL2563_REG_DATA0LOW | TSL2563_CLEARINT,
342 buf0, sizeof(buf0));
343 if (ret != sizeof(buf0))
344 goto out;
345
346 ret = tsl2563_read(client, TSL2563_REG_DATA1LOW,
347 buf1, sizeof(buf1));
348 if (ret != sizeof(buf1))
349 goto out;
350
351 adc0 = (buf0[1] << 8) + buf0[0];
352 adc1 = (buf1[1] << 8) + buf1[0];
353
354 retry = tsl2563_adjust_gainlevel(chip, adc0);
355 }
356
357 chip->data0 = normalize_adc(adc0, chip->gainlevel->gaintime);
358 chip->data1 = normalize_adc(adc1, chip->gainlevel->gaintime);
359
360 schedule_delayed_work(&chip->poweroff_work, 5 * HZ);
361
362 ret = 0;
363out:
364 return ret;
365}
366
367static inline int calib_to_sysfs(u32 calib)
368{
369 return (int) (((calib * CALIB_BASE_SYSFS) +
370 CALIB_FRAC_HALF) >> CALIB_FRAC_BITS);
371}
372
373static inline u32 calib_from_sysfs(int value)
374{
375 return (((u32) value) << CALIB_FRAC_BITS) / CALIB_BASE_SYSFS;
376}
377
378/*
379 * Conversions between lux and ADC values.
380 *
381 * The basic formula is lux = c0 * adc0 - c1 * adc1, where c0 and c1 are
382 * appropriate constants. Different constants are needed for different
383 * kinds of light, determined by the ratio adc1/adc0 (basically the ratio
384 * of the intensities in infrared and visible wavelengths). lux_table below
385 * lists the upper threshold of the adc1/adc0 ratio and the corresponding
386 * constants.
387 */
388
389struct tsl2563_lux_coeff {
390 unsigned long ch_ratio;
391 unsigned long ch0_coeff;
392 unsigned long ch1_coeff;
393};
394
395static const struct tsl2563_lux_coeff lux_table[] = {
396 {
397 .ch_ratio = FRAC10K(1300),
398 .ch0_coeff = FRAC10K(315),
399 .ch1_coeff = FRAC10K(262),
400 }, {
401 .ch_ratio = FRAC10K(2600),
402 .ch0_coeff = FRAC10K(337),
403 .ch1_coeff = FRAC10K(430),
404 }, {
405 .ch_ratio = FRAC10K(3900),
406 .ch0_coeff = FRAC10K(363),
407 .ch1_coeff = FRAC10K(529),
408 }, {
409 .ch_ratio = FRAC10K(5200),
410 .ch0_coeff = FRAC10K(392),
411 .ch1_coeff = FRAC10K(605),
412 }, {
413 .ch_ratio = FRAC10K(6500),
414 .ch0_coeff = FRAC10K(229),
415 .ch1_coeff = FRAC10K(291),
416 }, {
417 .ch_ratio = FRAC10K(8000),
418 .ch0_coeff = FRAC10K(157),
419 .ch1_coeff = FRAC10K(180),
420 }, {
421 .ch_ratio = FRAC10K(13000),
422 .ch0_coeff = FRAC10K(34),
423 .ch1_coeff = FRAC10K(26),
424 }, {
425 .ch_ratio = ULONG_MAX,
426 .ch0_coeff = 0,
427 .ch1_coeff = 0,
428 },
429};
430
431/*
432 * Convert normalized, scaled ADC values to lux.
433 */
434static unsigned int adc_to_lux(u32 adc0, u32 adc1)
435{
436 const struct tsl2563_lux_coeff *lp = lux_table;
437 unsigned long ratio, lux, ch0 = adc0, ch1 = adc1;
438
439 ratio = ch0 ? ((ch1 << ADC_FRAC_BITS) / ch0) : ULONG_MAX;
440
441 while (lp->ch_ratio < ratio)
442 lp++;
443
444 lux = ch0 * lp->ch0_coeff - ch1 * lp->ch1_coeff;
445
446 return (unsigned int) (lux >> ADC_FRAC_BITS);
447}
448
449/*--------------------------------------------------------------*/
450/* Sysfs interface */
451/*--------------------------------------------------------------*/
452
453static ssize_t tsl2563_adc0_show(struct device *dev,
454 struct device_attribute *attr, char *buf)
455{
456 struct iio_dev *indio_dev = dev_get_drvdata(dev);
457 struct tsl2563_chip *chip = indio_dev->dev_data;
458 int ret;
459
460 mutex_lock(&chip->lock);
461
462 ret = tsl2563_get_adc(chip);
463 if (ret)
464 goto out;
465
466 ret = snprintf(buf, PAGE_SIZE, "%d\n", chip->data0);
467out:
468 mutex_unlock(&chip->lock);
469 return ret;
470}
471
472static ssize_t tsl2563_adc1_show(struct device *dev,
473 struct device_attribute *attr, char *buf)
474{
475 struct iio_dev *indio_dev = dev_get_drvdata(dev);
476 struct tsl2563_chip *chip = indio_dev->dev_data;
477 int ret;
478
479 mutex_lock(&chip->lock);
480
481 ret = tsl2563_get_adc(chip);
482 if (ret)
483 goto out;
484
485 ret = snprintf(buf, PAGE_SIZE, "%d\n", chip->data1);
486out:
487 mutex_unlock(&chip->lock);
488 return ret;
489}
490
491/* Apply calibration coefficient to ADC count. */
492static u32 calib_adc(u32 adc, u32 calib)
493{
494 unsigned long scaled = adc;
495
496 scaled *= calib;
497 scaled >>= CALIB_FRAC_BITS;
498
499 return (u32) scaled;
500}
501
502static ssize_t tsl2563_lux_show(struct device *dev,
503 struct device_attribute *attr, char *buf)
504{
505 struct iio_dev *indio_dev = dev_get_drvdata(dev);
506 struct tsl2563_chip *chip = indio_dev->dev_data;
507 u32 calib0, calib1;
508 int ret;
509
510 mutex_lock(&chip->lock);
511
512 ret = tsl2563_get_adc(chip);
513 if (ret)
514 goto out;
515
516 calib0 = calib_adc(chip->data0, chip->calib0) * chip->cover_comp_gain;
517 calib1 = calib_adc(chip->data1, chip->calib1) * chip->cover_comp_gain;
518
519 ret = snprintf(buf, PAGE_SIZE, "%d\n", adc_to_lux(calib0, calib1));
520
521out:
522 mutex_unlock(&chip->lock);
523 return ret;
524}
525
526static ssize_t format_calib(char *buf, int len, u32 calib)
527{
528 return snprintf(buf, PAGE_SIZE, "%d\n", calib_to_sysfs(calib));
529}
530
531static ssize_t tsl2563_calib0_show(struct device *dev,
532 struct device_attribute *attr, char *buf)
533{
534 struct iio_dev *indio_dev = dev_get_drvdata(dev);
535 struct tsl2563_chip *chip = indio_dev->dev_data;
536 int ret;
537
538 mutex_lock(&chip->lock);
539 ret = format_calib(buf, PAGE_SIZE, chip->calib0);
540 mutex_unlock(&chip->lock);
541 return ret;
542}
543
544static ssize_t tsl2563_calib1_show(struct device *dev,
545 struct device_attribute *attr, char *buf)
546{
547 struct iio_dev *indio_dev = dev_get_drvdata(dev);
548 struct tsl2563_chip *chip = indio_dev->dev_data;
549 int ret;
550
551 mutex_lock(&chip->lock);
552 ret = format_calib(buf, PAGE_SIZE, chip->calib1);
553 mutex_unlock(&chip->lock);
554 return ret;
555}
556
557static int do_calib_store(struct device *dev, const char *buf, size_t len,
558 int ch)
559{
560 struct iio_dev *indio_dev = dev_get_drvdata(dev);
561 struct tsl2563_chip *chip = indio_dev->dev_data;
562 int value;
563 u32 calib;
564
565 if (1 != sscanf(buf, "%d", &value))
566 return -EINVAL;
567
568 calib = calib_from_sysfs(value);
569
570 if (ch)
571 chip->calib1 = calib;
572 else
573 chip->calib0 = calib;
574
575 return len;
576}
577
578static ssize_t tsl2563_calib0_store(struct device *dev,
579 struct device_attribute *attr,
580 const char *buf, size_t len)
581{
582 return do_calib_store(dev, buf, len, 0);
583}
584
585static ssize_t tsl2563_calib1_store(struct device *dev,
586 struct device_attribute *attr,
587 const char *buf, size_t len)
588{
589 return do_calib_store(dev, buf, len, 1);
590}
591
592/* AmitXXXX: Convert to IIO_DEV_ATTR_LIGHT* as in tsl2561
593 * once I understand what they mean */
594static DEVICE_ATTR(adc0, S_IRUGO, tsl2563_adc0_show, NULL);
595static DEVICE_ATTR(adc1, S_IRUGO, tsl2563_adc1_show, NULL);
596static DEVICE_ATTR(lux, S_IRUGO, tsl2563_lux_show, NULL);
597static DEVICE_ATTR(calib0, S_IRUGO | S_IWUSR,
598 tsl2563_calib0_show, tsl2563_calib0_store);
599static DEVICE_ATTR(calib1, S_IRUGO | S_IWUSR,
600 tsl2563_calib1_show, tsl2563_calib1_store);
601
602static struct attribute *tsl2563_attributes[] = {
603 &dev_attr_adc0.attr,
604 &dev_attr_adc1.attr,
605 &dev_attr_lux.attr,
606 &dev_attr_calib0.attr,
607 &dev_attr_calib1.attr,
608 NULL
609};
610
611static const struct attribute_group tsl2563_group = {
612 .attrs = tsl2563_attributes,
613};
614
615/*--------------------------------------------------------------*/
616/* Probe, Attach, Remove */
617/*--------------------------------------------------------------*/
618static struct i2c_driver tsl2563_i2c_driver;
619
620static int __devinit tsl2563_probe(struct i2c_client *client,
621 const struct i2c_device_id *device_id)
622{
623 struct tsl2563_chip *chip;
624 struct tsl2563_platform_data *pdata = client->dev.platform_data;
625 int err = 0;
626 int ret;
627 u8 id;
628
629 chip = kzalloc(sizeof(*chip), GFP_KERNEL);
630 if (!chip)
631 return -ENOMEM;
632
633 i2c_set_clientdata(client, chip);
634 chip->client = client;
635
636 err = tsl2563_detect(chip);
637 if (err) {
638 dev_err(&client->dev, "device not found, error %d \n", -err);
639 goto fail1;
640 }
641
642 err = tsl2563_read_id(chip, &id);
643 if (err)
644 goto fail1;
645
646 mutex_init(&chip->lock);
647
648 /* Default values used until userspace says otherwise */
649 chip->low_thres = 0x0;
650 chip->high_thres = 0xffff;
651 chip->gainlevel = tsl2563_gainlevel_table;
652 chip->intr = TSL2563_INT_PERSIST(4);
653 chip->calib0 = calib_from_sysfs(CALIB_BASE_SYSFS);
654 chip->calib1 = calib_from_sysfs(CALIB_BASE_SYSFS);
655
656 if (pdata)
657 chip->cover_comp_gain = pdata->cover_comp_gain;
658 else
659 chip->cover_comp_gain = 1;
660
661 dev_info(&client->dev, "model %d, rev. %d\n", id >> 4, id & 0x0f);
662
663 chip->indio_dev = iio_allocate_device();
664 if (!chip->indio_dev)
665 goto fail1;
666 chip->indio_dev->attrs = &tsl2563_group;
667 chip->indio_dev->dev.parent = &client->dev;
668 chip->indio_dev->dev_data = (void *)(chip);
669 chip->indio_dev->driver_module = THIS_MODULE;
670 chip->indio_dev->modes = INDIO_DIRECT_MODE;
671 ret = iio_device_register(chip->indio_dev);
672 if (ret)
673 goto fail1;
674
675 err = tsl2563_configure(chip);
676 if (err)
677 goto fail2;
678
679 INIT_DELAYED_WORK(&chip->poweroff_work, tsl2563_poweroff_work);
680 schedule_delayed_work(&chip->poweroff_work, 5 * HZ);
681
682 return 0;
683fail2:
684 iio_device_unregister(chip->indio_dev);
685fail1:
686 kfree(chip);
687 return err;
688}
689
690static int tsl2563_remove(struct i2c_client *client)
691{
692 struct tsl2563_chip *chip = i2c_get_clientdata(client);
693
694 iio_device_unregister(chip->indio_dev);
695
696 kfree(chip);
697 return 0;
698}
699
700static int tsl2563_suspend(struct i2c_client *client, pm_message_t state)
701{
702 struct tsl2563_chip *chip = i2c_get_clientdata(client);
703 int ret;
704
705 mutex_lock(&chip->lock);
706
707 ret = tsl2563_set_power(chip, 0);
708 if (ret)
709 goto out;
710
711 chip->state = state;
712
713out:
714 mutex_unlock(&chip->lock);
715 return ret;
716}
717
718static int tsl2563_resume(struct i2c_client *client)
719{
720 struct tsl2563_chip *chip = i2c_get_clientdata(client);
721 int ret;
722
723 mutex_lock(&chip->lock);
724
725 ret = tsl2563_set_power(chip, 1);
726 if (ret)
727 goto out;
728
729 ret = tsl2563_configure(chip);
730 if (ret)
731 goto out;
732
733 chip->state.event = PM_EVENT_ON;
734
735out:
736 mutex_unlock(&chip->lock);
737 return ret;
738}
739
740static const struct i2c_device_id tsl2563_id[] = {
741 { DRIVER_NAME, 0 },
742 { },
743};
744MODULE_DEVICE_TABLE(i2c, tsl2563_id);
745
746static struct i2c_driver tsl2563_i2c_driver = {
747 .driver = {
748 .name = DRIVER_NAME,
749 },
750 .suspend = tsl2563_suspend,
751 .resume = tsl2563_resume,
752 .probe = tsl2563_probe,
753 .remove = __devexit_p(tsl2563_remove),
754 .id_table = tsl2563_id,
755};
756
757static int __init tsl2563_init(void)
758{
759 return i2c_add_driver(&tsl2563_i2c_driver);
760}
761
762static void __exit tsl2563_exit(void)
763{
764 i2c_del_driver(&tsl2563_i2c_driver);
765}
766
767MODULE_AUTHOR("Nokia Corporation");
768MODULE_DESCRIPTION("tsl2563 light sensor driver");
769MODULE_LICENSE("GPL");
770
771module_init(tsl2563_init);
772module_exit(tsl2563_exit);
diff --git a/drivers/staging/iio/light/tsl2563.h b/drivers/staging/iio/light/tsl2563.h
new file mode 100644
index 000000000000..b97368bd7fff
--- /dev/null
+++ b/drivers/staging/iio/light/tsl2563.h
@@ -0,0 +1,9 @@
1#ifndef __LINUX_TSL2563_H
2#define __LINUX_TSL2563_H
3
4struct tsl2563_platform_data {
5 int cover_comp_gain;
6};
7
8#endif /* __LINUX_TSL2563_H */
9