954 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Device driver for monitoring ambient light intensity (lux)4 * within the TAOS tsl258x family of devices (tsl2580, tsl2581, tsl2583).5 *6 * Copyright (c) 2011, TAOS Corporation.7 * Copyright (c) 2016-2017 Brian Masney <masneyb@onstation.org>8 */9 10#include <linux/kernel.h>11#include <linux/i2c.h>12#include <linux/errno.h>13#include <linux/delay.h>14#include <linux/string.h>15#include <linux/mutex.h>16#include <linux/unistd.h>17#include <linux/slab.h>18#include <linux/module.h>19#include <linux/iio/iio.h>20#include <linux/iio/sysfs.h>21#include <linux/pm_runtime.h>22 23/* Device Registers and Masks */24#define TSL2583_CNTRL 0x0025#define TSL2583_ALS_TIME 0X0126#define TSL2583_INTERRUPT 0x0227#define TSL2583_GAIN 0x0728#define TSL2583_REVID 0x1129#define TSL2583_CHIPID 0x1230#define TSL2583_ALS_CHAN0LO 0x1431#define TSL2583_ALS_CHAN0HI 0x1532#define TSL2583_ALS_CHAN1LO 0x1633#define TSL2583_ALS_CHAN1HI 0x1734#define TSL2583_TMR_LO 0x1835#define TSL2583_TMR_HI 0x1936 37/* tsl2583 cmd reg masks */38#define TSL2583_CMD_REG 0x8039#define TSL2583_CMD_SPL_FN 0x6040#define TSL2583_CMD_ALS_INT_CLR 0x0141 42/* tsl2583 cntrl reg masks */43#define TSL2583_CNTL_ADC_ENBL 0x0244#define TSL2583_CNTL_PWR_OFF 0x0045#define TSL2583_CNTL_PWR_ON 0x0146 47/* tsl2583 status reg masks */48#define TSL2583_STA_ADC_VALID 0x0149#define TSL2583_STA_ADC_INTR 0x1050 51/* Lux calculation constants */52#define TSL2583_LUX_CALC_OVER_FLOW 6553553 54#define TSL2583_INTERRUPT_DISABLED 0x0055 56#define TSL2583_CHIP_ID 0x9057#define TSL2583_CHIP_ID_MASK 0xf058 59#define TSL2583_POWER_OFF_DELAY_MS 200060 61/* Per-device data */62struct tsl2583_als_info {63 u16 als_ch0;64 u16 als_ch1;65 u16 lux;66};67 68struct tsl2583_lux {69 unsigned int ratio;70 unsigned int ch0;71 unsigned int ch1;72};73 74static const struct tsl2583_lux tsl2583_default_lux[] = {75 { 9830, 8520, 15729 },76 { 12452, 10807, 23344 },77 { 14746, 6383, 11705 },78 { 17695, 4063, 6554 },79 { 0, 0, 0 } /* Termination segment */80};81 82#define TSL2583_MAX_LUX_TABLE_ENTRIES 1183 84struct tsl2583_settings {85 int als_time;86 int als_gain;87 int als_gain_trim;88 int als_cal_target;89 90 /*91 * This structure is intentionally large to accommodate updates via92 * sysfs. Sized to 11 = max 10 segments + 1 termination segment.93 * Assumption is that one and only one type of glass used.94 */95 struct tsl2583_lux als_device_lux[TSL2583_MAX_LUX_TABLE_ENTRIES];96};97 98struct tsl2583_chip {99 struct mutex als_mutex;100 struct i2c_client *client;101 struct tsl2583_als_info als_cur_info;102 struct tsl2583_settings als_settings;103 int als_time_scale;104 int als_saturation;105};106 107struct gainadj {108 s16 ch0;109 s16 ch1;110 s16 mean;111};112 113/* Index = (0 - 3) Used to validate the gain selection index */114static const struct gainadj gainadj[] = {115 { 1, 1, 1 },116 { 8, 8, 8 },117 { 16, 16, 16 },118 { 107, 115, 111 }119};120 121/*122 * Provides initial operational parameter defaults.123 * These defaults may be changed through the device's sysfs files.124 */125static void tsl2583_defaults(struct tsl2583_chip *chip)126{127 /*128 * The integration time must be a multiple of 50ms and within the129 * range [50, 600] ms.130 */131 chip->als_settings.als_time = 100;132 133 /*134 * This is an index into the gainadj table. Assume clear glass as the135 * default.136 */137 chip->als_settings.als_gain = 0;138 139 /* Default gain trim to account for aperture effects */140 chip->als_settings.als_gain_trim = 1000;141 142 /* Known external ALS reading used for calibration */143 chip->als_settings.als_cal_target = 130;144 145 /* Default lux table. */146 memcpy(chip->als_settings.als_device_lux, tsl2583_default_lux,147 sizeof(tsl2583_default_lux));148}149 150/*151 * Reads and calculates current lux value.152 * The raw ch0 and ch1 values of the ambient light sensed in the last153 * integration cycle are read from the device.154 * Time scale factor array values are adjusted based on the integration time.155 * The raw values are multiplied by a scale factor, and device gain is obtained156 * using gain index. Limit checks are done next, then the ratio of a multiple157 * of ch1 value, to the ch0 value, is calculated. The array als_device_lux[]158 * declared above is then scanned to find the first ratio value that is just159 * above the ratio we just calculated. The ch0 and ch1 multiplier constants in160 * the array are then used along with the time scale factor array values, to161 * calculate the lux.162 */163static int tsl2583_get_lux(struct iio_dev *indio_dev)164{165 u16 ch0, ch1; /* separated ch0/ch1 data from device */166 u32 lux; /* raw lux calculated from device data */167 u64 lux64;168 u32 ratio;169 u8 buf[5];170 struct tsl2583_lux *p;171 struct tsl2583_chip *chip = iio_priv(indio_dev);172 int i, ret;173 174 ret = i2c_smbus_read_byte_data(chip->client, TSL2583_CMD_REG);175 if (ret < 0) {176 dev_err(&chip->client->dev, "%s: failed to read CMD_REG register\n",177 __func__);178 goto done;179 }180 181 /* is data new & valid */182 if (!(ret & TSL2583_STA_ADC_INTR)) {183 dev_err(&chip->client->dev, "%s: data not valid; returning last value\n",184 __func__);185 ret = chip->als_cur_info.lux; /* return LAST VALUE */186 goto done;187 }188 189 for (i = 0; i < 4; i++) {190 int reg = TSL2583_CMD_REG | (TSL2583_ALS_CHAN0LO + i);191 192 ret = i2c_smbus_read_byte_data(chip->client, reg);193 if (ret < 0) {194 dev_err(&chip->client->dev, "%s: failed to read register %x\n",195 __func__, reg);196 goto done;197 }198 buf[i] = ret;199 }200 201 /*202 * Clear the pending interrupt status bit on the chip to allow the next203 * integration cycle to start. This has to be done even though this204 * driver currently does not support interrupts.205 */206 ret = i2c_smbus_write_byte(chip->client,207 (TSL2583_CMD_REG | TSL2583_CMD_SPL_FN |208 TSL2583_CMD_ALS_INT_CLR));209 if (ret < 0) {210 dev_err(&chip->client->dev, "%s: failed to clear the interrupt bit\n",211 __func__);212 goto done; /* have no data, so return failure */213 }214 215 /* extract ALS/lux data */216 ch0 = le16_to_cpup((const __le16 *)&buf[0]);217 ch1 = le16_to_cpup((const __le16 *)&buf[2]);218 219 chip->als_cur_info.als_ch0 = ch0;220 chip->als_cur_info.als_ch1 = ch1;221 222 if ((ch0 >= chip->als_saturation) || (ch1 >= chip->als_saturation))223 goto return_max;224 225 if (!ch0) {226 /*227 * The sensor appears to be in total darkness so set the228 * calculated lux to 0 and return early to avoid a division by229 * zero below when calculating the ratio.230 */231 ret = 0;232 chip->als_cur_info.lux = 0;233 goto done;234 }235 236 /* calculate ratio */237 ratio = (ch1 << 15) / ch0;238 239 /* convert to unscaled lux using the pointer to the table */240 for (p = (struct tsl2583_lux *)chip->als_settings.als_device_lux;241 p->ratio != 0 && p->ratio < ratio; p++)242 ;243 244 if (p->ratio == 0) {245 lux = 0;246 } else {247 u32 ch0lux, ch1lux;248 249 ch0lux = ((ch0 * p->ch0) +250 (gainadj[chip->als_settings.als_gain].ch0 >> 1))251 / gainadj[chip->als_settings.als_gain].ch0;252 ch1lux = ((ch1 * p->ch1) +253 (gainadj[chip->als_settings.als_gain].ch1 >> 1))254 / gainadj[chip->als_settings.als_gain].ch1;255 256 /* note: lux is 31 bit max at this point */257 if (ch1lux > ch0lux) {258 dev_dbg(&chip->client->dev, "%s: No Data - Returning 0\n",259 __func__);260 ret = 0;261 chip->als_cur_info.lux = 0;262 goto done;263 }264 265 lux = ch0lux - ch1lux;266 }267 268 /* adjust for active time scale */269 if (chip->als_time_scale == 0)270 lux = 0;271 else272 lux = (lux + (chip->als_time_scale >> 1)) /273 chip->als_time_scale;274 275 /*276 * Adjust for active gain scale.277 * The tsl2583_default_lux tables above have a factor of 8192 built in,278 * so we need to shift right.279 * User-specified gain provides a multiplier.280 * Apply user-specified gain before shifting right to retain precision.281 * Use 64 bits to avoid overflow on multiplication.282 * Then go back to 32 bits before division to avoid using div_u64().283 */284 lux64 = lux;285 lux64 = lux64 * chip->als_settings.als_gain_trim;286 lux64 >>= 13;287 lux = lux64;288 lux = DIV_ROUND_CLOSEST(lux, 1000);289 290 if (lux > TSL2583_LUX_CALC_OVER_FLOW) { /* check for overflow */291return_max:292 lux = TSL2583_LUX_CALC_OVER_FLOW;293 }294 295 /* Update the structure with the latest VALID lux. */296 chip->als_cur_info.lux = lux;297 ret = lux;298 299done:300 return ret;301}302 303/*304 * Obtain single reading and calculate the als_gain_trim (later used305 * to derive actual lux).306 * Return updated gain_trim value.307 */308static int tsl2583_als_calibrate(struct iio_dev *indio_dev)309{310 struct tsl2583_chip *chip = iio_priv(indio_dev);311 unsigned int gain_trim_val;312 int ret;313 int lux_val;314 315 ret = i2c_smbus_read_byte_data(chip->client,316 TSL2583_CMD_REG | TSL2583_CNTRL);317 if (ret < 0) {318 dev_err(&chip->client->dev,319 "%s: failed to read from the CNTRL register\n",320 __func__);321 return ret;322 }323 324 if ((ret & (TSL2583_CNTL_ADC_ENBL | TSL2583_CNTL_PWR_ON))325 != (TSL2583_CNTL_ADC_ENBL | TSL2583_CNTL_PWR_ON)) {326 dev_err(&chip->client->dev,327 "%s: Device is not powered on and/or ADC is not enabled\n",328 __func__);329 return -EINVAL;330 } else if ((ret & TSL2583_STA_ADC_VALID) != TSL2583_STA_ADC_VALID) {331 dev_err(&chip->client->dev,332 "%s: The two ADC channels have not completed an integration cycle\n",333 __func__);334 return -ENODATA;335 }336 337 lux_val = tsl2583_get_lux(indio_dev);338 if (lux_val < 0) {339 dev_err(&chip->client->dev, "%s: failed to get lux\n",340 __func__);341 return lux_val;342 }343 344 /* Avoid division by zero of lux_value later on */345 if (lux_val == 0) {346 dev_err(&chip->client->dev,347 "%s: lux_val of 0 will produce out of range trim_value\n",348 __func__);349 return -ENODATA;350 }351 352 gain_trim_val = (unsigned int)(((chip->als_settings.als_cal_target)353 * chip->als_settings.als_gain_trim) / lux_val);354 if ((gain_trim_val < 250) || (gain_trim_val > 4000)) {355 dev_err(&chip->client->dev,356 "%s: trim_val of %d is not within the range [250, 4000]\n",357 __func__, gain_trim_val);358 return -ENODATA;359 }360 361 chip->als_settings.als_gain_trim = (int)gain_trim_val;362 363 return 0;364}365 366static int tsl2583_set_als_time(struct tsl2583_chip *chip)367{368 int als_count, als_time, ret;369 u8 val;370 371 /* determine als integration register */372 als_count = DIV_ROUND_CLOSEST(chip->als_settings.als_time * 100, 270);373 if (!als_count)374 als_count = 1; /* ensure at least one cycle */375 376 /* convert back to time (encompasses overrides) */377 als_time = DIV_ROUND_CLOSEST(als_count * 27, 10);378 379 val = 256 - als_count;380 ret = i2c_smbus_write_byte_data(chip->client,381 TSL2583_CMD_REG | TSL2583_ALS_TIME,382 val);383 if (ret < 0) {384 dev_err(&chip->client->dev, "%s: failed to set the als time to %d\n",385 __func__, val);386 return ret;387 }388 389 /* set chip struct re scaling and saturation */390 chip->als_saturation = als_count * 922; /* 90% of full scale */391 chip->als_time_scale = DIV_ROUND_CLOSEST(als_time, 50);392 393 return ret;394}395 396static int tsl2583_set_als_gain(struct tsl2583_chip *chip)397{398 int ret;399 400 /* Set the gain based on als_settings struct */401 ret = i2c_smbus_write_byte_data(chip->client,402 TSL2583_CMD_REG | TSL2583_GAIN,403 chip->als_settings.als_gain);404 if (ret < 0)405 dev_err(&chip->client->dev,406 "%s: failed to set the gain to %d\n", __func__,407 chip->als_settings.als_gain);408 409 return ret;410}411 412static int tsl2583_set_power_state(struct tsl2583_chip *chip, u8 state)413{414 int ret;415 416 ret = i2c_smbus_write_byte_data(chip->client,417 TSL2583_CMD_REG | TSL2583_CNTRL, state);418 if (ret < 0)419 dev_err(&chip->client->dev,420 "%s: failed to set the power state to %d\n", __func__,421 state);422 423 return ret;424}425 426/*427 * Turn the device on.428 * Configuration must be set before calling this function.429 */430static int tsl2583_chip_init_and_power_on(struct iio_dev *indio_dev)431{432 struct tsl2583_chip *chip = iio_priv(indio_dev);433 int ret;434 435 /* Power on the device; ADC off. */436 ret = tsl2583_set_power_state(chip, TSL2583_CNTL_PWR_ON);437 if (ret < 0)438 return ret;439 440 ret = i2c_smbus_write_byte_data(chip->client,441 TSL2583_CMD_REG | TSL2583_INTERRUPT,442 TSL2583_INTERRUPT_DISABLED);443 if (ret < 0) {444 dev_err(&chip->client->dev,445 "%s: failed to disable interrupts\n", __func__);446 return ret;447 }448 449 ret = tsl2583_set_als_time(chip);450 if (ret < 0)451 return ret;452 453 ret = tsl2583_set_als_gain(chip);454 if (ret < 0)455 return ret;456 457 usleep_range(3000, 3500);458 459 ret = tsl2583_set_power_state(chip, TSL2583_CNTL_PWR_ON |460 TSL2583_CNTL_ADC_ENBL);461 if (ret < 0)462 return ret;463 464 return ret;465}466 467/* Sysfs Interface Functions */468 469static ssize_t in_illuminance_input_target_show(struct device *dev,470 struct device_attribute *attr,471 char *buf)472{473 struct iio_dev *indio_dev = dev_to_iio_dev(dev);474 struct tsl2583_chip *chip = iio_priv(indio_dev);475 int ret;476 477 mutex_lock(&chip->als_mutex);478 ret = sprintf(buf, "%d\n", chip->als_settings.als_cal_target);479 mutex_unlock(&chip->als_mutex);480 481 return ret;482}483 484static ssize_t in_illuminance_input_target_store(struct device *dev,485 struct device_attribute *attr,486 const char *buf, size_t len)487{488 struct iio_dev *indio_dev = dev_to_iio_dev(dev);489 struct tsl2583_chip *chip = iio_priv(indio_dev);490 int value;491 492 if (kstrtoint(buf, 0, &value) || !value)493 return -EINVAL;494 495 mutex_lock(&chip->als_mutex);496 chip->als_settings.als_cal_target = value;497 mutex_unlock(&chip->als_mutex);498 499 return len;500}501 502static ssize_t in_illuminance_calibrate_store(struct device *dev,503 struct device_attribute *attr,504 const char *buf, size_t len)505{506 struct iio_dev *indio_dev = dev_to_iio_dev(dev);507 struct tsl2583_chip *chip = iio_priv(indio_dev);508 int value, ret;509 510 if (kstrtoint(buf, 0, &value) || value != 1)511 return -EINVAL;512 513 mutex_lock(&chip->als_mutex);514 515 ret = tsl2583_als_calibrate(indio_dev);516 if (ret < 0)517 goto done;518 519 ret = len;520done:521 mutex_unlock(&chip->als_mutex);522 523 return ret;524}525 526static ssize_t in_illuminance_lux_table_show(struct device *dev,527 struct device_attribute *attr,528 char *buf)529{530 struct iio_dev *indio_dev = dev_to_iio_dev(dev);531 struct tsl2583_chip *chip = iio_priv(indio_dev);532 unsigned int i;533 int offset = 0;534 535 for (i = 0; i < ARRAY_SIZE(chip->als_settings.als_device_lux); i++) {536 offset += sprintf(buf + offset, "%u,%u,%u,",537 chip->als_settings.als_device_lux[i].ratio,538 chip->als_settings.als_device_lux[i].ch0,539 chip->als_settings.als_device_lux[i].ch1);540 if (chip->als_settings.als_device_lux[i].ratio == 0) {541 /*542 * We just printed the first "0" entry.543 * Now get rid of the extra "," and break.544 */545 offset--;546 break;547 }548 }549 550 offset += sprintf(buf + offset, "\n");551 552 return offset;553}554 555static ssize_t in_illuminance_lux_table_store(struct device *dev,556 struct device_attribute *attr,557 const char *buf, size_t len)558{559 struct iio_dev *indio_dev = dev_to_iio_dev(dev);560 struct tsl2583_chip *chip = iio_priv(indio_dev);561 const unsigned int max_ints = TSL2583_MAX_LUX_TABLE_ENTRIES * 3;562 int value[TSL2583_MAX_LUX_TABLE_ENTRIES * 3 + 1];563 int ret = -EINVAL;564 unsigned int n;565 566 mutex_lock(&chip->als_mutex);567 568 get_options(buf, ARRAY_SIZE(value), value);569 570 /*571 * We now have an array of ints starting at value[1], and572 * enumerated by value[0].573 * We expect each group of three ints is one table entry,574 * and the last table entry is all 0.575 */576 n = value[0];577 if ((n % 3) || n < 6 || n > max_ints) {578 dev_err(dev,579 "%s: The number of entries in the lux table must be a multiple of 3 and within the range [6, %d]\n",580 __func__, max_ints);581 goto done;582 }583 if ((value[n - 2] | value[n - 1] | value[n]) != 0) {584 dev_err(dev, "%s: The last 3 entries in the lux table must be zeros.\n",585 __func__);586 goto done;587 }588 589 memcpy(chip->als_settings.als_device_lux, &value[1],590 value[0] * sizeof(value[1]));591 592 ret = len;593 594done:595 mutex_unlock(&chip->als_mutex);596 597 return ret;598}599 600static IIO_CONST_ATTR(in_illuminance_calibscale_available, "1 8 16 111");601static IIO_CONST_ATTR(in_illuminance_integration_time_available,602 "0.050 0.100 0.150 0.200 0.250 0.300 0.350 0.400 0.450 0.500 0.550 0.600 0.650");603static IIO_DEVICE_ATTR_RW(in_illuminance_input_target, 0);604static IIO_DEVICE_ATTR_WO(in_illuminance_calibrate, 0);605static IIO_DEVICE_ATTR_RW(in_illuminance_lux_table, 0);606 607static struct attribute *sysfs_attrs_ctrl[] = {608 &iio_const_attr_in_illuminance_calibscale_available.dev_attr.attr,609 &iio_const_attr_in_illuminance_integration_time_available.dev_attr.attr,610 &iio_dev_attr_in_illuminance_input_target.dev_attr.attr,611 &iio_dev_attr_in_illuminance_calibrate.dev_attr.attr,612 &iio_dev_attr_in_illuminance_lux_table.dev_attr.attr,613 NULL614};615 616static const struct attribute_group tsl2583_attribute_group = {617 .attrs = sysfs_attrs_ctrl,618};619 620static const struct iio_chan_spec tsl2583_channels[] = {621 {622 .type = IIO_LIGHT,623 .modified = 1,624 .channel2 = IIO_MOD_LIGHT_IR,625 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),626 },627 {628 .type = IIO_LIGHT,629 .modified = 1,630 .channel2 = IIO_MOD_LIGHT_BOTH,631 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),632 },633 {634 .type = IIO_LIGHT,635 .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |636 BIT(IIO_CHAN_INFO_CALIBBIAS) |637 BIT(IIO_CHAN_INFO_CALIBSCALE) |638 BIT(IIO_CHAN_INFO_INT_TIME),639 },640};641 642static int tsl2583_set_pm_runtime_busy(struct tsl2583_chip *chip, bool on)643{644 int ret;645 646 if (on) {647 ret = pm_runtime_resume_and_get(&chip->client->dev);648 } else {649 pm_runtime_mark_last_busy(&chip->client->dev);650 ret = pm_runtime_put_autosuspend(&chip->client->dev);651 }652 653 return ret;654}655 656static int tsl2583_read_raw(struct iio_dev *indio_dev,657 struct iio_chan_spec const *chan,658 int *val, int *val2, long mask)659{660 struct tsl2583_chip *chip = iio_priv(indio_dev);661 int ret, pm_ret;662 663 ret = tsl2583_set_pm_runtime_busy(chip, true);664 if (ret < 0)665 return ret;666 667 mutex_lock(&chip->als_mutex);668 669 ret = -EINVAL;670 switch (mask) {671 case IIO_CHAN_INFO_RAW:672 if (chan->type == IIO_LIGHT) {673 ret = tsl2583_get_lux(indio_dev);674 if (ret < 0)675 goto read_done;676 677 /*678 * From page 20 of the TSL2581, TSL2583 data679 * sheet (TAOS134 − MARCH 2011):680 *681 * One of the photodiodes (channel 0) is682 * sensitive to both visible and infrared light,683 * while the second photodiode (channel 1) is684 * sensitive primarily to infrared light.685 */686 if (chan->channel2 == IIO_MOD_LIGHT_BOTH)687 *val = chip->als_cur_info.als_ch0;688 else689 *val = chip->als_cur_info.als_ch1;690 691 ret = IIO_VAL_INT;692 }693 break;694 case IIO_CHAN_INFO_PROCESSED:695 if (chan->type == IIO_LIGHT) {696 ret = tsl2583_get_lux(indio_dev);697 if (ret < 0)698 goto read_done;699 700 *val = ret;701 ret = IIO_VAL_INT;702 }703 break;704 case IIO_CHAN_INFO_CALIBBIAS:705 if (chan->type == IIO_LIGHT) {706 *val = chip->als_settings.als_gain_trim;707 ret = IIO_VAL_INT;708 }709 break;710 case IIO_CHAN_INFO_CALIBSCALE:711 if (chan->type == IIO_LIGHT) {712 *val = gainadj[chip->als_settings.als_gain].mean;713 ret = IIO_VAL_INT;714 }715 break;716 case IIO_CHAN_INFO_INT_TIME:717 if (chan->type == IIO_LIGHT) {718 *val = 0;719 *val2 = chip->als_settings.als_time;720 ret = IIO_VAL_INT_PLUS_MICRO;721 }722 break;723 default:724 break;725 }726 727read_done:728 mutex_unlock(&chip->als_mutex);729 730 if (ret < 0) {731 tsl2583_set_pm_runtime_busy(chip, false);732 return ret;733 }734 735 /*736 * Preserve the ret variable if the call to737 * tsl2583_set_pm_runtime_busy() is successful so the reading738 * (if applicable) is returned to user space.739 */740 pm_ret = tsl2583_set_pm_runtime_busy(chip, false);741 if (pm_ret < 0)742 return pm_ret;743 744 return ret;745}746 747static int tsl2583_write_raw(struct iio_dev *indio_dev,748 struct iio_chan_spec const *chan,749 int val, int val2, long mask)750{751 struct tsl2583_chip *chip = iio_priv(indio_dev);752 int ret;753 754 ret = tsl2583_set_pm_runtime_busy(chip, true);755 if (ret < 0)756 return ret;757 758 mutex_lock(&chip->als_mutex);759 760 ret = -EINVAL;761 switch (mask) {762 case IIO_CHAN_INFO_CALIBBIAS:763 if (chan->type == IIO_LIGHT) {764 chip->als_settings.als_gain_trim = val;765 ret = 0;766 }767 break;768 case IIO_CHAN_INFO_CALIBSCALE:769 if (chan->type == IIO_LIGHT) {770 unsigned int i;771 772 for (i = 0; i < ARRAY_SIZE(gainadj); i++) {773 if (gainadj[i].mean == val) {774 chip->als_settings.als_gain = i;775 ret = tsl2583_set_als_gain(chip);776 break;777 }778 }779 }780 break;781 case IIO_CHAN_INFO_INT_TIME:782 if (chan->type == IIO_LIGHT && !val && val2 >= 50 &&783 val2 <= 650 && !(val2 % 50)) {784 chip->als_settings.als_time = val2;785 ret = tsl2583_set_als_time(chip);786 }787 break;788 default:789 break;790 }791 792 mutex_unlock(&chip->als_mutex);793 794 if (ret < 0) {795 tsl2583_set_pm_runtime_busy(chip, false);796 return ret;797 }798 799 ret = tsl2583_set_pm_runtime_busy(chip, false);800 if (ret < 0)801 return ret;802 803 return ret;804}805 806static const struct iio_info tsl2583_info = {807 .attrs = &tsl2583_attribute_group,808 .read_raw = tsl2583_read_raw,809 .write_raw = tsl2583_write_raw,810};811 812static int tsl2583_probe(struct i2c_client *clientp)813{814 int ret;815 struct tsl2583_chip *chip;816 struct iio_dev *indio_dev;817 818 if (!i2c_check_functionality(clientp->adapter,819 I2C_FUNC_SMBUS_BYTE_DATA)) {820 dev_err(&clientp->dev, "%s: i2c smbus byte data functionality is unsupported\n",821 __func__);822 return -EOPNOTSUPP;823 }824 825 indio_dev = devm_iio_device_alloc(&clientp->dev, sizeof(*chip));826 if (!indio_dev)827 return -ENOMEM;828 829 chip = iio_priv(indio_dev);830 chip->client = clientp;831 i2c_set_clientdata(clientp, indio_dev);832 833 mutex_init(&chip->als_mutex);834 835 ret = i2c_smbus_read_byte_data(clientp,836 TSL2583_CMD_REG | TSL2583_CHIPID);837 if (ret < 0) {838 dev_err(&clientp->dev,839 "%s: failed to read the chip ID register\n", __func__);840 return ret;841 }842 843 if ((ret & TSL2583_CHIP_ID_MASK) != TSL2583_CHIP_ID) {844 dev_err(&clientp->dev, "%s: received an unknown chip ID %x\n",845 __func__, ret);846 return -EINVAL;847 }848 849 indio_dev->info = &tsl2583_info;850 indio_dev->channels = tsl2583_channels;851 indio_dev->num_channels = ARRAY_SIZE(tsl2583_channels);852 indio_dev->modes = INDIO_DIRECT_MODE;853 indio_dev->name = chip->client->name;854 855 pm_runtime_enable(&clientp->dev);856 pm_runtime_set_autosuspend_delay(&clientp->dev,857 TSL2583_POWER_OFF_DELAY_MS);858 pm_runtime_use_autosuspend(&clientp->dev);859 860 ret = iio_device_register(indio_dev);861 if (ret) {862 dev_err(&clientp->dev, "%s: iio registration failed\n",863 __func__);864 return ret;865 }866 867 /* Load up the V2 defaults (these are hard coded defaults for now) */868 tsl2583_defaults(chip);869 870 dev_info(&clientp->dev, "Light sensor found.\n");871 872 return 0;873}874 875static void tsl2583_remove(struct i2c_client *client)876{877 struct iio_dev *indio_dev = i2c_get_clientdata(client);878 struct tsl2583_chip *chip = iio_priv(indio_dev);879 880 iio_device_unregister(indio_dev);881 882 pm_runtime_disable(&client->dev);883 pm_runtime_set_suspended(&client->dev);884 885 tsl2583_set_power_state(chip, TSL2583_CNTL_PWR_OFF);886}887 888static int tsl2583_suspend(struct device *dev)889{890 struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));891 struct tsl2583_chip *chip = iio_priv(indio_dev);892 int ret;893 894 mutex_lock(&chip->als_mutex);895 896 ret = tsl2583_set_power_state(chip, TSL2583_CNTL_PWR_OFF);897 898 mutex_unlock(&chip->als_mutex);899 900 return ret;901}902 903static int tsl2583_resume(struct device *dev)904{905 struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));906 struct tsl2583_chip *chip = iio_priv(indio_dev);907 int ret;908 909 mutex_lock(&chip->als_mutex);910 911 ret = tsl2583_chip_init_and_power_on(indio_dev);912 913 mutex_unlock(&chip->als_mutex);914 915 return ret;916}917 918static DEFINE_RUNTIME_DEV_PM_OPS(tsl2583_pm_ops, tsl2583_suspend,919 tsl2583_resume, NULL);920 921static const struct i2c_device_id tsl2583_idtable[] = {922 { "tsl2580", 0 },923 { "tsl2581", 1 },924 { "tsl2583", 2 },925 {}926};927MODULE_DEVICE_TABLE(i2c, tsl2583_idtable);928 929static const struct of_device_id tsl2583_of_match[] = {930 { .compatible = "amstaos,tsl2580", },931 { .compatible = "amstaos,tsl2581", },932 { .compatible = "amstaos,tsl2583", },933 { },934};935MODULE_DEVICE_TABLE(of, tsl2583_of_match);936 937/* Driver definition */938static struct i2c_driver tsl2583_driver = {939 .driver = {940 .name = "tsl2583",941 .pm = pm_ptr(&tsl2583_pm_ops),942 .of_match_table = tsl2583_of_match,943 },944 .id_table = tsl2583_idtable,945 .probe = tsl2583_probe,946 .remove = tsl2583_remove,947};948module_i2c_driver(tsl2583_driver);949 950MODULE_AUTHOR("J. August Brenner <jbrenner@taosinc.com>");951MODULE_AUTHOR("Brian Masney <masneyb@onstation.org>");952MODULE_DESCRIPTION("TAOS tsl2583 ambient light sensor driver");953MODULE_LICENSE("GPL");954