2
* Device driver for monitoring ambient light intensity (lux)
3
* within the TAOS tsl258x family of devices (tsl2580, tsl2581).
5
* Copyright (c) 2011, TAOS Corporation.
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.
12
* This program is distributed in the hope that it will be useful, but WITHOUT
13
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17
* You should have received a copy of the GNU General Public License along
18
* with this program; if not, write to the Free Software Foundation, Inc.,
19
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22
#include <linux/kernel.h>
23
#include <linux/i2c.h>
24
#include <linux/errno.h>
25
#include <linux/delay.h>
26
#include <linux/string.h>
27
#include <linux/mutex.h>
28
#include <linux/unistd.h>
29
#include <linux/slab.h>
30
#include <linux/module.h>
33
#define TSL258X_MAX_DEVICE_REGS 32
35
/* Triton register offsets */
36
#define TSL258X_REG_MAX 8
38
/* Device Registers and Masks */
39
#define TSL258X_CNTRL 0x00
40
#define TSL258X_ALS_TIME 0X01
41
#define TSL258X_INTERRUPT 0x02
42
#define TSL258X_GAIN 0x07
43
#define TSL258X_REVID 0x11
44
#define TSL258X_CHIPID 0x12
45
#define TSL258X_ALS_CHAN0LO 0x14
46
#define TSL258X_ALS_CHAN0HI 0x15
47
#define TSL258X_ALS_CHAN1LO 0x16
48
#define TSL258X_ALS_CHAN1HI 0x17
49
#define TSL258X_TMR_LO 0x18
50
#define TSL258X_TMR_HI 0x19
52
/* tsl2583 cmd reg masks */
53
#define TSL258X_CMD_REG 0x80
54
#define TSL258X_CMD_SPL_FN 0x60
55
#define TSL258X_CMD_ALS_INT_CLR 0X01
57
/* tsl2583 cntrl reg masks */
58
#define TSL258X_CNTL_ADC_ENBL 0x02
59
#define TSL258X_CNTL_PWR_ON 0x01
61
/* tsl2583 status reg masks */
62
#define TSL258X_STA_ADC_VALID 0x01
63
#define TSL258X_STA_ADC_INTR 0x10
65
/* Lux calculation constants */
66
#define TSL258X_LUX_CALC_OVER_FLOW 65535
69
TSL258X_CHIP_UNKNOWN = 0,
70
TSL258X_CHIP_WORKING = 1,
71
TSL258X_CHIP_SUSPENDED = 2
75
struct taos_als_info {
81
struct taos_settings {
89
struct mutex als_mutex;
90
struct i2c_client *client;
91
struct taos_als_info als_cur_info;
92
struct taos_settings taos_settings;
100
* Initial values for device - this values can/will be changed by driver.
101
* and applications as needed.
102
* These values are dynamic.
104
static const u8 taos_config[8] = {
105
0x00, 0xee, 0x00, 0x03, 0x00, 0xFF, 0xFF, 0x00
106
}; /* cntrl atime intC Athl0 Athl1 Athh0 Athh1 gain */
114
/* This structure is intentionally large to accommodate updates via sysfs. */
115
/* Sized to 11 = max 10 segments + 1 termination segment */
116
/* Assumption is is one and only one type of glass used */
117
static struct taos_lux taos_device_lux[11] = {
118
{ 9830, 8520, 15729 },
119
{ 12452, 10807, 23344 },
120
{ 14746, 6383, 11705 },
121
{ 17695, 4063, 6554 },
129
/* Index = (0 - 3) Used to validate the gain selection index */
130
static const struct gainadj gainadj[] = {
138
* Provides initial operational parameter defaults.
139
* These defaults may be changed through the device's sysfs files.
141
static void taos_defaults(struct tsl2583_chip *chip)
143
/* Operational parameters */
144
chip->taos_settings.als_time = 100;
145
/* must be a multiple of 50mS */
146
chip->taos_settings.als_gain = 0;
147
/* this is actually an index into the gain table */
148
/* assume clear glass as default */
149
chip->taos_settings.als_gain_trim = 1000;
150
/* default gain trim to account for aperture effects */
151
chip->taos_settings.als_cal_target = 130;
152
/* Known external ALS reading used for calibration */
156
* Read a number of bytes starting at register (reg) location.
157
* Return 0, or i2c_smbus_write_byte ERROR code.
160
taos_i2c_read(struct i2c_client *client, u8 reg, u8 *val, unsigned int len)
164
for (i = 0; i < len; i++) {
165
/* select register to write */
166
ret = i2c_smbus_write_byte(client, (TSL258X_CMD_REG | reg));
168
dev_err(&client->dev, "taos_i2c_read failed to write"
169
" register %x\n", reg);
173
*val = i2c_smbus_read_byte(client);
181
* Reads and calculates current lux value.
182
* The raw ch0 and ch1 values of the ambient light sensed in the last
183
* integration cycle are read from the device.
184
* Time scale factor array values are adjusted based on the integration time.
185
* The raw values are multiplied by a scale factor, and device gain is obtained
186
* using gain index. Limit checks are done next, then the ratio of a multiple
187
* of ch1 value, to the ch0 value, is calculated. The array taos_device_lux[]
188
* declared above is then scanned to find the first ratio value that is just
189
* above the ratio we just calculated. The ch0 and ch1 multiplier constants in
190
* the array are then used along with the time scale factor array values, to
193
static int taos_get_lux(struct iio_dev *indio_dev)
195
u16 ch0, ch1; /* separated ch0/ch1 data from device */
196
u32 lux; /* raw lux calculated from device data */
200
struct tsl2583_chip *chip = iio_priv(indio_dev);
205
if (mutex_trylock(&chip->als_mutex) == 0) {
206
dev_info(&chip->client->dev, "taos_get_lux device is busy\n");
207
return chip->als_cur_info.lux; /* busy, so return LAST VALUE */
210
if (chip->taos_chip_status != TSL258X_CHIP_WORKING) {
211
/* device is not enabled */
212
dev_err(&chip->client->dev, "taos_get_lux device is not enabled\n");
217
ret = taos_i2c_read(chip->client, (TSL258X_CMD_REG), &buf[0], 1);
219
dev_err(&chip->client->dev, "taos_get_lux failed to read CMD_REG\n");
222
/* is data new & valid */
223
if (!(buf[0] & TSL258X_STA_ADC_INTR)) {
224
dev_err(&chip->client->dev, "taos_get_lux data not valid\n");
225
ret = chip->als_cur_info.lux; /* return LAST VALUE */
229
for (i = 0; i < 4; i++) {
230
int reg = TSL258X_CMD_REG | (TSL258X_ALS_CHAN0LO + i);
231
ret = taos_i2c_read(chip->client, reg, &buf[i], 1);
233
dev_err(&chip->client->dev, "taos_get_lux failed to read"
234
" register %x\n", reg);
239
/* clear status, really interrupt status (interrupts are off), but
240
* we use the bit anyway - don't forget 0x80 - this is a command*/
241
ret = i2c_smbus_write_byte(chip->client,
242
(TSL258X_CMD_REG | TSL258X_CMD_SPL_FN |
243
TSL258X_CMD_ALS_INT_CLR));
246
dev_err(&chip->client->dev,
247
"taos_i2c_write_command failed in taos_get_lux, err = %d\n",
249
goto out_unlock; /* have no data, so return failure */
252
/* extract ALS/lux data */
253
ch0 = le16_to_cpup((const __le16 *)&buf[0]);
254
ch1 = le16_to_cpup((const __le16 *)&buf[2]);
256
chip->als_cur_info.als_ch0 = ch0;
257
chip->als_cur_info.als_ch1 = ch1;
259
if ((ch0 >= chip->als_saturation) || (ch1 >= chip->als_saturation))
263
/* have no data, so return LAST VALUE */
264
ret = chip->als_cur_info.lux = 0;
267
/* calculate ratio */
268
ratio = (ch1 << 15) / ch0;
269
/* convert to unscaled lux using the pointer to the table */
270
for (p = (struct taos_lux *) taos_device_lux;
271
p->ratio != 0 && p->ratio < ratio; p++)
277
ch0lux = ((ch0 * p->ch0) +
278
(gainadj[chip->taos_settings.als_gain].ch0 >> 1))
279
/ gainadj[chip->taos_settings.als_gain].ch0;
280
ch1lux = ((ch1 * p->ch1) +
281
(gainadj[chip->taos_settings.als_gain].ch1 >> 1))
282
/ gainadj[chip->taos_settings.als_gain].ch1;
283
lux = ch0lux - ch1lux;
286
/* note: lux is 31 bit max at this point */
287
if (ch1lux > ch0lux) {
288
dev_dbg(&chip->client->dev, "No Data - Return last value\n");
289
ret = chip->als_cur_info.lux = 0;
293
/* adjust for active time scale */
294
if (chip->als_time_scale == 0)
297
lux = (lux + (chip->als_time_scale >> 1)) /
298
chip->als_time_scale;
300
/* adjust for active gain scale */
301
lux >>= 13; /* tables have factor of 8192 builtin for accuracy */
302
lux = (lux * chip->taos_settings.als_gain_trim + 500) / 1000;
303
if (lux > TSL258X_LUX_CALC_OVER_FLOW) { /* check for overflow */
305
lux = TSL258X_LUX_CALC_OVER_FLOW;
308
/* Update the structure with the latest VALID lux. */
309
chip->als_cur_info.lux = lux;
313
mutex_unlock(&chip->als_mutex);
318
* Obtain single reading and calculate the als_gain_trim (later used
319
* to derive actual lux).
320
* Return updated gain_trim value.
322
static int taos_als_calibrate(struct iio_dev *indio_dev)
324
struct tsl2583_chip *chip = iio_priv(indio_dev);
326
unsigned int gain_trim_val;
330
ret = i2c_smbus_write_byte(chip->client,
331
(TSL258X_CMD_REG | TSL258X_CNTRL));
333
dev_err(&chip->client->dev,
334
"taos_als_calibrate failed to reach the CNTRL register, ret=%d\n",
339
reg_val = i2c_smbus_read_byte(chip->client);
340
if ((reg_val & (TSL258X_CNTL_ADC_ENBL | TSL258X_CNTL_PWR_ON))
341
!= (TSL258X_CNTL_ADC_ENBL | TSL258X_CNTL_PWR_ON)) {
342
dev_err(&chip->client->dev,
343
"taos_als_calibrate failed: device not powered on with ADC enabled\n");
347
ret = i2c_smbus_write_byte(chip->client,
348
(TSL258X_CMD_REG | TSL258X_CNTRL));
350
dev_err(&chip->client->dev,
351
"taos_als_calibrate failed to reach the STATUS register, ret=%d\n",
355
reg_val = i2c_smbus_read_byte(chip->client);
357
if ((reg_val & TSL258X_STA_ADC_VALID) != TSL258X_STA_ADC_VALID) {
358
dev_err(&chip->client->dev,
359
"taos_als_calibrate failed: STATUS - ADC not valid.\n");
362
lux_val = taos_get_lux(indio_dev);
364
dev_err(&chip->client->dev, "taos_als_calibrate failed to get lux\n");
367
gain_trim_val = (unsigned int) (((chip->taos_settings.als_cal_target)
368
* chip->taos_settings.als_gain_trim) / lux_val);
370
if ((gain_trim_val < 250) || (gain_trim_val > 4000)) {
371
dev_err(&chip->client->dev,
372
"taos_als_calibrate failed: trim_val of %d is out of range\n",
376
chip->taos_settings.als_gain_trim = (int) gain_trim_val;
378
return (int) gain_trim_val;
382
* Turn the device on.
383
* Configuration must be set before calling this function.
385
static int taos_chip_on(struct iio_dev *indio_dev)
393
struct tsl2583_chip *chip = iio_priv(indio_dev);
395
/* and make sure we're not already on */
396
if (chip->taos_chip_status == TSL258X_CHIP_WORKING) {
397
/* if forcing a register update - turn off, then on */
398
dev_info(&chip->client->dev, "device is already enabled\n");
402
/* determine als integration regster */
403
als_count = (chip->taos_settings.als_time * 100 + 135) / 270;
405
als_count = 1; /* ensure at least one cycle */
407
/* convert back to time (encompasses overrides) */
408
als_time = (als_count * 27 + 5) / 10;
409
chip->taos_config[TSL258X_ALS_TIME] = 256 - als_count;
411
/* Set the gain based on taos_settings struct */
412
chip->taos_config[TSL258X_GAIN] = chip->taos_settings.als_gain;
414
/* set chip struct re scaling and saturation */
415
chip->als_saturation = als_count * 922; /* 90% of full scale */
416
chip->als_time_scale = (als_time + 25) / 50;
418
/* TSL258x Specific power-on / adc enable sequence
419
* Power on the device 1st. */
420
utmp = TSL258X_CNTL_PWR_ON;
421
ret = i2c_smbus_write_byte_data(chip->client,
422
TSL258X_CMD_REG | TSL258X_CNTRL, utmp);
424
dev_err(&chip->client->dev, "taos_chip_on failed on CNTRL reg.\n");
428
/* Use the following shadow copy for our delay before enabling ADC.
429
* Write all the registers. */
430
for (i = 0, uP = chip->taos_config; i < TSL258X_REG_MAX; i++) {
431
ret = i2c_smbus_write_byte_data(chip->client,
435
dev_err(&chip->client->dev,
436
"taos_chip_on failed on reg %d.\n", i);
442
/* NOW enable the ADC
443
* initialize the desired mode of operation */
444
utmp = TSL258X_CNTL_PWR_ON | TSL258X_CNTL_ADC_ENBL;
445
ret = i2c_smbus_write_byte_data(chip->client,
446
TSL258X_CMD_REG | TSL258X_CNTRL,
449
dev_err(&chip->client->dev, "taos_chip_on failed on 2nd CTRL reg.\n");
452
chip->taos_chip_status = TSL258X_CHIP_WORKING;
457
static int taos_chip_off(struct iio_dev *indio_dev)
459
struct tsl2583_chip *chip = iio_priv(indio_dev);
462
/* turn device off */
463
chip->taos_chip_status = TSL258X_CHIP_SUSPENDED;
464
ret = i2c_smbus_write_byte_data(chip->client,
465
TSL258X_CMD_REG | TSL258X_CNTRL,
470
/* Sysfs Interface Functions */
472
static ssize_t taos_power_state_show(struct device *dev,
473
struct device_attribute *attr, char *buf)
475
struct iio_dev *indio_dev = dev_get_drvdata(dev);
476
struct tsl2583_chip *chip = iio_priv(indio_dev);
478
return sprintf(buf, "%d\n", chip->taos_chip_status);
481
static ssize_t taos_power_state_store(struct device *dev,
482
struct device_attribute *attr, const char *buf, size_t len)
484
struct iio_dev *indio_dev = dev_get_drvdata(dev);
487
if (strict_strtoul(buf, 0, &value))
491
taos_chip_off(indio_dev);
493
taos_chip_on(indio_dev);
498
static ssize_t taos_gain_show(struct device *dev,
499
struct device_attribute *attr, char *buf)
501
struct iio_dev *indio_dev = dev_get_drvdata(dev);
502
struct tsl2583_chip *chip = iio_priv(indio_dev);
505
switch (chip->taos_settings.als_gain) {
520
return sprintf(buf, "%s\n", gain);
523
static ssize_t taos_gain_store(struct device *dev,
524
struct device_attribute *attr, const char *buf, size_t len)
526
struct iio_dev *indio_dev = dev_get_drvdata(dev);
527
struct tsl2583_chip *chip = iio_priv(indio_dev);
530
if (strict_strtoul(buf, 0, &value))
535
chip->taos_settings.als_gain = 0;
538
chip->taos_settings.als_gain = 1;
541
chip->taos_settings.als_gain = 2;
544
chip->taos_settings.als_gain = 3;
547
dev_err(dev, "Invalid Gain Index (must be 1,8,16,111)\n");
554
static ssize_t taos_gain_available_show(struct device *dev,
555
struct device_attribute *attr, char *buf)
557
return sprintf(buf, "%s\n", "1 8 16 111");
560
static ssize_t taos_als_time_show(struct device *dev,
561
struct device_attribute *attr, char *buf)
563
struct iio_dev *indio_dev = dev_get_drvdata(dev);
564
struct tsl2583_chip *chip = iio_priv(indio_dev);
566
return sprintf(buf, "%d\n", chip->taos_settings.als_time);
569
static ssize_t taos_als_time_store(struct device *dev,
570
struct device_attribute *attr, const char *buf, size_t len)
572
struct iio_dev *indio_dev = dev_get_drvdata(dev);
573
struct tsl2583_chip *chip = iio_priv(indio_dev);
576
if (strict_strtoul(buf, 0, &value))
579
if ((value < 50) || (value > 650))
585
chip->taos_settings.als_time = value;
590
static ssize_t taos_als_time_available_show(struct device *dev,
591
struct device_attribute *attr, char *buf)
593
return sprintf(buf, "%s\n",
594
"50 100 150 200 250 300 350 400 450 500 550 600 650");
597
static ssize_t taos_als_trim_show(struct device *dev,
598
struct device_attribute *attr, char *buf)
600
struct iio_dev *indio_dev = dev_get_drvdata(dev);
601
struct tsl2583_chip *chip = iio_priv(indio_dev);
603
return sprintf(buf, "%d\n", chip->taos_settings.als_gain_trim);
606
static ssize_t taos_als_trim_store(struct device *dev,
607
struct device_attribute *attr, const char *buf, size_t len)
609
struct iio_dev *indio_dev = dev_get_drvdata(dev);
610
struct tsl2583_chip *chip = iio_priv(indio_dev);
613
if (strict_strtoul(buf, 0, &value))
617
chip->taos_settings.als_gain_trim = value;
622
static ssize_t taos_als_cal_target_show(struct device *dev,
623
struct device_attribute *attr, char *buf)
625
struct iio_dev *indio_dev = dev_get_drvdata(dev);
626
struct tsl2583_chip *chip = iio_priv(indio_dev);
628
return sprintf(buf, "%d\n", chip->taos_settings.als_cal_target);
631
static ssize_t taos_als_cal_target_store(struct device *dev,
632
struct device_attribute *attr, const char *buf, size_t len)
634
struct iio_dev *indio_dev = dev_get_drvdata(dev);
635
struct tsl2583_chip *chip = iio_priv(indio_dev);
638
if (strict_strtoul(buf, 0, &value))
642
chip->taos_settings.als_cal_target = value;
647
static ssize_t taos_lux_show(struct device *dev, struct device_attribute *attr,
652
ret = taos_get_lux(dev_get_drvdata(dev));
656
return sprintf(buf, "%d\n", ret);
659
static ssize_t taos_do_calibrate(struct device *dev,
660
struct device_attribute *attr, const char *buf, size_t len)
662
struct iio_dev *indio_dev = dev_get_drvdata(dev);
665
if (strict_strtoul(buf, 0, &value))
669
taos_als_calibrate(indio_dev);
674
static ssize_t taos_luxtable_show(struct device *dev,
675
struct device_attribute *attr, char *buf)
680
for (i = 0; i < ARRAY_SIZE(taos_device_lux); i++) {
681
offset += sprintf(buf + offset, "%d,%d,%d,",
682
taos_device_lux[i].ratio,
683
taos_device_lux[i].ch0,
684
taos_device_lux[i].ch1);
685
if (taos_device_lux[i].ratio == 0) {
686
/* We just printed the first "0" entry.
687
* Now get rid of the extra "," and break. */
693
offset += sprintf(buf + offset, "\n");
697
static ssize_t taos_luxtable_store(struct device *dev,
698
struct device_attribute *attr, const char *buf, size_t len)
700
struct iio_dev *indio_dev = dev_get_drvdata(dev);
701
struct tsl2583_chip *chip = iio_priv(indio_dev);
702
int value[ARRAY_SIZE(taos_device_lux)*3 + 1];
705
get_options(buf, ARRAY_SIZE(value), value);
707
/* We now have an array of ints starting at value[1], and
708
* enumerated by value[0].
709
* We expect each group of three ints is one table entry,
710
* and the last table entry is all 0.
713
if ((n % 3) || n < 6 || n > ((ARRAY_SIZE(taos_device_lux) - 1) * 3)) {
714
dev_info(dev, "LUX TABLE INPUT ERROR 1 Value[0]=%d\n", n);
717
if ((value[(n - 2)] | value[(n - 1)] | value[n]) != 0) {
718
dev_info(dev, "LUX TABLE INPUT ERROR 2 Value[0]=%d\n", n);
722
if (chip->taos_chip_status == TSL258X_CHIP_WORKING)
723
taos_chip_off(indio_dev);
725
/* Zero out the table */
726
memset(taos_device_lux, 0, sizeof(taos_device_lux));
727
memcpy(taos_device_lux, &value[1], (value[0] * 4));
729
taos_chip_on(indio_dev);
734
static DEVICE_ATTR(power_state, S_IRUGO | S_IWUSR,
735
taos_power_state_show, taos_power_state_store);
737
static DEVICE_ATTR(illuminance0_calibscale, S_IRUGO | S_IWUSR,
738
taos_gain_show, taos_gain_store);
739
static DEVICE_ATTR(illuminance0_calibscale_available, S_IRUGO,
740
taos_gain_available_show, NULL);
742
static DEVICE_ATTR(illuminance0_integration_time, S_IRUGO | S_IWUSR,
743
taos_als_time_show, taos_als_time_store);
744
static DEVICE_ATTR(illuminance0_integration_time_available, S_IRUGO,
745
taos_als_time_available_show, NULL);
747
static DEVICE_ATTR(illuminance0_calibbias, S_IRUGO | S_IWUSR,
748
taos_als_trim_show, taos_als_trim_store);
750
static DEVICE_ATTR(illuminance0_input_target, S_IRUGO | S_IWUSR,
751
taos_als_cal_target_show, taos_als_cal_target_store);
753
static DEVICE_ATTR(illuminance0_input, S_IRUGO, taos_lux_show, NULL);
754
static DEVICE_ATTR(illuminance0_calibrate, S_IWUSR, NULL, taos_do_calibrate);
755
static DEVICE_ATTR(illuminance0_lux_table, S_IRUGO | S_IWUSR,
756
taos_luxtable_show, taos_luxtable_store);
758
static struct attribute *sysfs_attrs_ctrl[] = {
759
&dev_attr_power_state.attr,
760
&dev_attr_illuminance0_calibscale.attr, /* Gain */
761
&dev_attr_illuminance0_calibscale_available.attr,
762
&dev_attr_illuminance0_integration_time.attr, /* I time*/
763
&dev_attr_illuminance0_integration_time_available.attr,
764
&dev_attr_illuminance0_calibbias.attr, /* trim */
765
&dev_attr_illuminance0_input_target.attr,
766
&dev_attr_illuminance0_input.attr,
767
&dev_attr_illuminance0_calibrate.attr,
768
&dev_attr_illuminance0_lux_table.attr,
772
static struct attribute_group tsl2583_attribute_group = {
773
.attrs = sysfs_attrs_ctrl,
776
/* Use the default register values to identify the Taos device */
777
static int taos_tsl258x_device(unsigned char *bufp)
779
return ((bufp[TSL258X_CHIPID] & 0xf0) == 0x90);
782
static const struct iio_info tsl2583_info = {
783
.attrs = &tsl2583_attribute_group,
784
.driver_module = THIS_MODULE,
788
* Client probe function - When a valid device is found, the driver's device
789
* data structure is updated, and initialization completes successfully.
791
static int __devinit taos_probe(struct i2c_client *clientp,
792
const struct i2c_device_id *idp)
795
unsigned char buf[TSL258X_MAX_DEVICE_REGS];
796
struct tsl2583_chip *chip;
797
struct iio_dev *indio_dev;
799
if (!i2c_check_functionality(clientp->adapter,
800
I2C_FUNC_SMBUS_BYTE_DATA)) {
801
dev_err(&clientp->dev,
802
"taos_probe() - i2c smbus byte data "
803
"functions unsupported\n");
807
indio_dev = iio_allocate_device(sizeof(*chip));
808
if (indio_dev == NULL) {
810
dev_err(&clientp->dev, "iio allocation failed\n");
813
chip = iio_priv(indio_dev);
814
chip->client = clientp;
815
i2c_set_clientdata(clientp, indio_dev);
817
mutex_init(&chip->als_mutex);
818
chip->taos_chip_status = TSL258X_CHIP_UNKNOWN;
819
memcpy(chip->taos_config, taos_config, sizeof(chip->taos_config));
821
for (i = 0; i < TSL258X_MAX_DEVICE_REGS; i++) {
822
ret = i2c_smbus_write_byte(clientp,
823
(TSL258X_CMD_REG | (TSL258X_CNTRL + i)));
825
dev_err(&clientp->dev, "i2c_smbus_write_bytes() to cmd "
826
"reg failed in taos_probe(), err = %d\n", ret);
829
ret = i2c_smbus_read_byte(clientp);
831
dev_err(&clientp->dev, "i2c_smbus_read_byte from "
832
"reg failed in taos_probe(), err = %d\n", ret);
839
if (!taos_tsl258x_device(buf)) {
840
dev_info(&clientp->dev, "i2c device found but does not match "
841
"expected id in taos_probe()\n");
845
ret = i2c_smbus_write_byte(clientp, (TSL258X_CMD_REG | TSL258X_CNTRL));
847
dev_err(&clientp->dev, "i2c_smbus_write_byte() to cmd reg "
848
"failed in taos_probe(), err = %d\n", ret);
852
indio_dev->info = &tsl2583_info;
853
indio_dev->dev.parent = &clientp->dev;
854
indio_dev->modes = INDIO_DIRECT_MODE;
855
indio_dev->name = chip->client->name;
856
ret = iio_device_register(indio_dev);
858
dev_err(&clientp->dev, "iio registration failed\n");
862
/* Load up the V2 defaults (these are hard coded defaults for now) */
865
/* Make sure the chip is on */
866
taos_chip_on(indio_dev);
868
dev_info(&clientp->dev, "Light sensor found.\n");
871
iio_free_device(indio_dev);
876
static int taos_suspend(struct i2c_client *client, pm_message_t state)
878
struct iio_dev *indio_dev = i2c_get_clientdata(client);
879
struct tsl2583_chip *chip = iio_priv(indio_dev);
882
mutex_lock(&chip->als_mutex);
884
if (chip->taos_chip_status == TSL258X_CHIP_WORKING) {
885
ret = taos_chip_off(indio_dev);
886
chip->taos_chip_status = TSL258X_CHIP_SUSPENDED;
889
mutex_unlock(&chip->als_mutex);
893
static int taos_resume(struct i2c_client *client)
895
struct iio_dev *indio_dev = i2c_get_clientdata(client);
896
struct tsl2583_chip *chip = iio_priv(indio_dev);
899
mutex_lock(&chip->als_mutex);
901
if (chip->taos_chip_status == TSL258X_CHIP_SUSPENDED)
902
ret = taos_chip_on(indio_dev);
904
mutex_unlock(&chip->als_mutex);
909
static int __devexit taos_remove(struct i2c_client *client)
911
iio_device_unregister(i2c_get_clientdata(client));
912
iio_free_device(i2c_get_clientdata(client));
917
static struct i2c_device_id taos_idtable[] = {
923
MODULE_DEVICE_TABLE(i2c, taos_idtable);
925
/* Driver definition */
926
static struct i2c_driver taos_driver = {
930
.id_table = taos_idtable,
931
.suspend = taos_suspend,
932
.resume = taos_resume,
934
.remove = __devexit_p(taos_remove),
937
static int __init taos_init(void)
939
return i2c_add_driver(&taos_driver);
942
static void __exit taos_exit(void)
944
i2c_del_driver(&taos_driver);
947
module_init(taos_init);
948
module_exit(taos_exit);
950
MODULE_AUTHOR("J. August Brenner<jbrenner@taosinc.com>");
951
MODULE_DESCRIPTION("TAOS tsl2583 ambient light sensor driver");
952
MODULE_LICENSE("GPL");