diff options
Diffstat (limited to 'drivers/staging/iio/light')
-rw-r--r-- | drivers/staging/iio/light/Kconfig | 6 | ||||
-rw-r--r-- | drivers/staging/iio/light/isl29018.c | 271 | ||||
-rw-r--r-- | drivers/staging/iio/light/tsl2563.c | 176 | ||||
-rw-r--r-- | drivers/staging/iio/light/tsl2583.c | 222 |
4 files changed, 365 insertions, 310 deletions
diff --git a/drivers/staging/iio/light/Kconfig b/drivers/staging/iio/light/Kconfig index 46d62d1..e7e9159 100644 --- a/drivers/staging/iio/light/Kconfig +++ b/drivers/staging/iio/light/Kconfig @@ -1,7 +1,7 @@ -\# +# # Light sensors # -comment "Light sensors" +menu "Light sensors" config SENSORS_ISL29018 tristate "ISL 29018 light and proximity sensor" @@ -30,3 +30,5 @@ config TSL2583 help Provides support for the TAOS tsl2580, tsl2581 and tsl2583 devices. Access ALS data via iio, sysfs. + +endmenu diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c index 4794ffd..9dc9e63 100644 --- a/drivers/staging/iio/light/isl29018.c +++ b/drivers/staging/iio/light/isl29018.c @@ -28,7 +28,7 @@ #include <linux/delay.h> #include <linux/slab.h> #include "../iio.h" - +#include "../sysfs.h" #define CONVERSION_TIME_MS 100 #define ISL29018_REG_ADD_COMMAND1 0x00 @@ -51,12 +51,16 @@ #define ISL29018_REG_ADD_DATA_LSB 0x02 #define ISL29018_REG_ADD_DATA_MSB 0x03 -#define ISL29018_MAX_REGS ISL29018_REG_ADD_DATA_MSB +#define ISL29018_MAX_REGS (ISL29018_REG_ADD_DATA_MSB+1) + +#define ISL29018_REG_TEST 0x08 +#define ISL29018_TEST_SHIFT 0 +#define ISL29018_TEST_MASK (0xFF << ISL29018_TEST_SHIFT) struct isl29018_chip { - struct iio_dev *indio_dev; struct i2c_client *client; struct mutex lock; + unsigned int lux_scale; unsigned int range; unsigned int adc_bit; int prox_scheme; @@ -66,22 +70,27 @@ struct isl29018_chip { static int isl29018_write_data(struct i2c_client *client, u8 reg, u8 val, u8 mask, u8 shift) { - u8 regval; - int ret = 0; - struct isl29018_chip *chip = i2c_get_clientdata(client); - - regval = chip->reg_cache[reg]; - regval &= ~mask; - regval |= val << shift; + u8 regval = val; + int ret; + struct isl29018_chip *chip = iio_priv(i2c_get_clientdata(client)); + + /* don't cache or mask REG_TEST */ + if (reg < ISL29018_MAX_REGS) { + regval = chip->reg_cache[reg]; + regval &= ~mask; + regval |= val << shift; + } ret = i2c_smbus_write_byte_data(client, reg, regval); if (ret) { dev_err(&client->dev, "Write to device fails status %x\n", ret); - return ret; + } else { + /* don't update cache on err */ + if (reg < ISL29018_MAX_REGS) + chip->reg_cache[reg] = regval; } - chip->reg_cache[reg] = regval; - return 0; + return ret; } static int isl29018_set_range(struct i2c_client *client, unsigned long range, @@ -158,7 +167,7 @@ static int isl29018_read_sensor_input(struct i2c_client *client, int mode) static int isl29018_read_lux(struct i2c_client *client, int *lux) { int lux_data; - struct isl29018_chip *chip = i2c_get_clientdata(client); + struct isl29018_chip *chip = iio_priv(i2c_get_clientdata(client)); lux_data = isl29018_read_sensor_input(client, COMMMAND1_OPMODE_ALS_ONCE); @@ -166,7 +175,7 @@ static int isl29018_read_lux(struct i2c_client *client, int *lux) if (lux_data < 0) return lux_data; - *lux = (lux_data * chip->range) >> chip->adc_bit; + *lux = (lux_data * chip->range * chip->lux_scale) >> chip->adc_bit; return 0; } @@ -224,52 +233,13 @@ static int isl29018_read_proximity_ir(struct i2c_client *client, int scheme, return 0; } -static ssize_t get_sensor_data(struct device *dev, char *buf, int mode) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct isl29018_chip *chip = indio_dev->dev_data; - struct i2c_client *client = chip->client; - int value = 0; - int status; - - mutex_lock(&chip->lock); - switch (mode) { - case COMMMAND1_OPMODE_PROX_ONCE: - status = isl29018_read_proximity_ir(client, - chip->prox_scheme, &value); - break; - - case COMMMAND1_OPMODE_ALS_ONCE: - status = isl29018_read_lux(client, &value); - break; - - case COMMMAND1_OPMODE_IR_ONCE: - status = isl29018_read_ir(client, &value); - break; - - default: - dev_err(&client->dev, "Mode %d is not supported\n", mode); - mutex_unlock(&chip->lock); - return -EBUSY; - } - if (status < 0) { - dev_err(&client->dev, "Error in Reading data"); - mutex_unlock(&chip->lock); - return status; - } - - mutex_unlock(&chip->lock); - - return sprintf(buf, "%d\n", value); -} - /* Sysfs interface */ /* range */ static ssize_t show_range(struct device *dev, struct device_attribute *attr, char *buf) { struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct isl29018_chip *chip = indio_dev->dev_data; + struct isl29018_chip *chip = iio_priv(indio_dev); return sprintf(buf, "%u\n", chip->range); } @@ -278,7 +248,7 @@ static ssize_t store_range(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct isl29018_chip *chip = indio_dev->dev_data; + struct isl29018_chip *chip = iio_priv(indio_dev); struct i2c_client *client = chip->client; int status; unsigned long lval; @@ -311,7 +281,7 @@ static ssize_t show_resolution(struct device *dev, struct device_attribute *attr, char *buf) { struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct isl29018_chip *chip = indio_dev->dev_data; + struct isl29018_chip *chip = iio_priv(indio_dev); return sprintf(buf, "%u\n", chip->adc_bit); } @@ -320,7 +290,7 @@ static ssize_t store_resolution(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct isl29018_chip *chip = indio_dev->dev_data; + struct isl29018_chip *chip = iio_priv(indio_dev); struct i2c_client *client = chip->client; int status; unsigned long lval; @@ -351,7 +321,7 @@ static ssize_t show_prox_infrared_supression(struct device *dev, struct device_attribute *attr, char *buf) { struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct isl29018_chip *chip = indio_dev->dev_data; + struct isl29018_chip *chip = iio_priv(indio_dev); /* return the "proximity scheme" i.e. if the chip does on chip infrared supression (1 means perform on chip supression) */ @@ -362,7 +332,7 @@ static ssize_t store_prox_infrared_supression(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct isl29018_chip *chip = indio_dev->dev_data; + struct isl29018_chip *chip = iio_priv(indio_dev); unsigned long lval; if (strict_strtoul(buf, 10, &lval)) @@ -381,27 +351,87 @@ static ssize_t store_prox_infrared_supression(struct device *dev, return count; } -/* Read lux */ -static ssize_t show_lux(struct device *dev, - struct device_attribute *devattr, char *buf) +/* Channel IO */ +static int isl29018_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) { - return get_sensor_data(dev, buf, COMMMAND1_OPMODE_ALS_ONCE); -} + struct isl29018_chip *chip = iio_priv(indio_dev); + int ret = -EINVAL; -/* Read ir */ -static ssize_t show_ir(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - return get_sensor_data(dev, buf, COMMMAND1_OPMODE_IR_ONCE); + mutex_lock(&chip->lock); + if (mask == (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE) && + chan->type == IIO_LIGHT) { + chip->lux_scale = val; + ret = 0; + } + mutex_unlock(&chip->lock); + + return 0; } -/* Read nearest ir */ -static ssize_t show_proxim_ir(struct device *dev, - struct device_attribute *devattr, char *buf) +static int isl29018_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long mask) { - return get_sensor_data(dev, buf, COMMMAND1_OPMODE_PROX_ONCE); + int ret = -EINVAL; + struct isl29018_chip *chip = iio_priv(indio_dev); + struct i2c_client *client = chip->client; + + mutex_lock(&chip->lock); + switch (mask) { + case 0: + switch (chan->type) { + case IIO_LIGHT: + ret = isl29018_read_lux(client, val); + break; + case IIO_INTENSITY: + ret = isl29018_read_ir(client, val); + break; + case IIO_PROXIMITY: + ret = isl29018_read_proximity_ir(client, + chip->prox_scheme, val); + break; + default: + break; + } + if (!ret) + ret = IIO_VAL_INT; + break; + case (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE): + if (chan->type == IIO_LIGHT) { + *val = chip->lux_scale; + ret = IIO_VAL_INT; + } + break; + default: + break; + } + mutex_unlock(&chip->lock); + return ret; } +static const struct iio_chan_spec isl29018_channels[] = { + { + .type = IIO_LIGHT, + .indexed = 1, + .channel = 0, + .processed_val = IIO_PROCESSED, + .info_mask = (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE), + }, { + .type = IIO_INTENSITY, + .modified = 1, + .channel2 = IIO_MOD_LIGHT_IR, + }, { + /* Unindexed in current ABI. But perhaps it should be. */ + .type = IIO_PROXIMITY, + } +}; + static IIO_DEVICE_ATTR(range, S_IRUGO | S_IWUSR, show_range, store_range, 0); static IIO_CONST_ATTR(range_available, "1000 4000 16000 64000"); static IIO_CONST_ATTR(adc_resolution_available, "4 8 12 16"); @@ -411,9 +441,6 @@ static IIO_DEVICE_ATTR(proximity_on_chip_ambient_infrared_supression, S_IRUGO | S_IWUSR, show_prox_infrared_supression, store_prox_infrared_supression, 0); -static IIO_DEVICE_ATTR(illuminance0_input, S_IRUGO, show_lux, NULL, 0); -static IIO_DEVICE_ATTR(intensity_infrared_raw, S_IRUGO, show_ir, NULL, 0); -static IIO_DEVICE_ATTR(proximity_raw, S_IRUGO, show_proxim_ir, NULL, 0); #define ISL29018_DEV_ATTR(name) (&iio_dev_attr_##name.dev_attr.attr) #define ISL29018_CONST_ATTR(name) (&iio_const_attr_##name.dev_attr.attr) @@ -423,9 +450,6 @@ static struct attribute *isl29018_attributes[] = { ISL29018_DEV_ATTR(adc_resolution), ISL29018_CONST_ATTR(adc_resolution_available), ISL29018_DEV_ATTR(proximity_on_chip_ambient_infrared_supression), - ISL29018_DEV_ATTR(illuminance0_input), - ISL29018_DEV_ATTR(intensity_infrared_raw), - ISL29018_DEV_ATTR(proximity_raw), NULL }; @@ -435,13 +459,55 @@ static const struct attribute_group isl29108_group = { static int isl29018_chip_init(struct i2c_client *client) { - struct isl29018_chip *chip = i2c_get_clientdata(client); + struct isl29018_chip *chip = iio_priv(i2c_get_clientdata(client)); int status; int new_adc_bit; unsigned int new_range; memset(chip->reg_cache, 0, sizeof(chip->reg_cache)); + /* Code added per Intersil Application Note 1534: + * When VDD sinks to approximately 1.8V or below, some of + * the part's registers may change their state. When VDD + * recovers to 2.25V (or greater), the part may thus be in an + * unknown mode of operation. The user can return the part to + * a known mode of operation either by (a) setting VDD = 0V for + * 1 second or more and then powering back up with a slew rate + * of 0.5V/ms or greater, or (b) via I2C disable all ALS/PROX + * conversions, clear the test registers, and then rewrite all + * registers to the desired values. + * ... + * FOR ISL29011, ISL29018, ISL29021, ISL29023 + * 1. Write 0x00 to register 0x08 (TEST) + * 2. Write 0x00 to register 0x00 (CMD1) + * 3. Rewrite all registers to the desired values + * + * ISL29018 Data Sheet (FN6619.1, Feb 11, 2010) essentially says + * the same thing EXCEPT the data sheet asks for a 1ms delay after + * writing the CMD1 register. + */ + status = isl29018_write_data(client, ISL29018_REG_TEST, 0, + ISL29018_TEST_MASK, ISL29018_TEST_SHIFT); + if (status < 0) { + dev_err(&client->dev, "Failed to clear isl29018 TEST reg." + "(%d)\n", status); + return status; + } + + /* See Intersil AN1534 comments above. + * "Operating Mode" (COMMAND1) register is reprogrammed when + * data is read from the device. + */ + status = isl29018_write_data(client, ISL29018_REG_ADD_COMMAND1, 0, + 0xff, 0); + if (status < 0) { + dev_err(&client->dev, "Failed to clear isl29018 CMD1 reg." + "(%d)\n", status); + return status; + } + + msleep(1); /* per data sheet, page 10 */ + /* set defaults */ status = isl29018_set_range(client, chip->range, &new_range); if (status < 0) { @@ -458,44 +524,45 @@ static int isl29018_chip_init(struct i2c_client *client) static const struct iio_info isl29108_info = { .attrs = &isl29108_group, .driver_module = THIS_MODULE, + .read_raw = &isl29018_read_raw, + .write_raw = &isl29018_write_raw, }; static int __devinit isl29018_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct isl29018_chip *chip; + struct iio_dev *indio_dev; int err; - chip = kzalloc(sizeof(struct isl29018_chip), GFP_KERNEL); - if (!chip) { - dev_err(&client->dev, "Memory allocation fails\n"); + indio_dev = iio_allocate_device(sizeof(*chip)); + if (indio_dev == NULL) { + dev_err(&client->dev, "iio allocation fails\n"); err = -ENOMEM; goto exit; } + chip = iio_priv(indio_dev); - i2c_set_clientdata(client, chip); + i2c_set_clientdata(client, indio_dev); chip->client = client; mutex_init(&chip->lock); + chip->lux_scale = 1; chip->range = 1000; chip->adc_bit = 16; err = isl29018_chip_init(client); if (err) - goto exit_free; + goto exit_iio_free; - chip->indio_dev = iio_allocate_device(0); - if (!chip->indio_dev) { - dev_err(&client->dev, "iio allocation fails\n"); - goto exit_free; - } - chip->indio_dev->info = &isl29108_info; - chip->indio_dev->name = id->name; - chip->indio_dev->dev.parent = &client->dev; - chip->indio_dev->dev_data = (void *)(chip); - chip->indio_dev->modes = INDIO_DIRECT_MODE; - err = iio_device_register(chip->indio_dev); + indio_dev->info = &isl29108_info; + indio_dev->channels = isl29018_channels; + indio_dev->num_channels = ARRAY_SIZE(isl29018_channels); + indio_dev->name = id->name; + indio_dev->dev.parent = &client->dev; + indio_dev->modes = INDIO_DIRECT_MODE; + err = iio_device_register(indio_dev); if (err) { dev_err(&client->dev, "iio registration fails\n"); goto exit_iio_free; @@ -503,20 +570,18 @@ static int __devinit isl29018_probe(struct i2c_client *client, return 0; exit_iio_free: - iio_free_device(chip->indio_dev); -exit_free: - kfree(chip); + iio_free_device(indio_dev); exit: return err; } static int __devexit isl29018_remove(struct i2c_client *client) { - struct isl29018_chip *chip = i2c_get_clientdata(client); + struct iio_dev *indio_dev = i2c_get_clientdata(client); dev_dbg(&client->dev, "%s()\n", __func__); - iio_device_unregister(chip->indio_dev); - kfree(chip); + iio_device_unregister(indio_dev); + iio_free_device(indio_dev); return 0; } diff --git a/drivers/staging/iio/light/tsl2563.c b/drivers/staging/iio/light/tsl2563.c index 9cffa2e..7e984bc 100644 --- a/drivers/staging/iio/light/tsl2563.c +++ b/drivers/staging/iio/light/tsl2563.c @@ -31,13 +31,12 @@ #include <linux/sched.h> #include <linux/mutex.h> #include <linux/delay.h> -#include <linux/platform_device.h> #include <linux/pm.h> -#include <linux/hwmon.h> #include <linux/err.h> #include <linux/slab.h> #include "../iio.h" +#include "../sysfs.h" #include "tsl2563.h" /* Use this many bits for fraction part. */ @@ -137,37 +136,14 @@ struct tsl2563_chip { u32 data1; }; -static int tsl2563_write(struct i2c_client *client, u8 reg, u8 value) -{ - int ret; - u8 buf[2]; - - buf[0] = TSL2563_CMD | reg; - buf[1] = value; - - ret = i2c_master_send(client, buf, sizeof(buf)); - return (ret == sizeof(buf)) ? 0 : ret; -} - -static int tsl2563_read(struct i2c_client *client, u8 reg, void *buf, int len) -{ - int ret; - u8 cmd = TSL2563_CMD | reg; - - ret = i2c_master_send(client, &cmd, sizeof(cmd)); - if (ret != sizeof(cmd)) - return ret; - - return i2c_master_recv(client, buf, len); -} - static int tsl2563_set_power(struct tsl2563_chip *chip, int on) { struct i2c_client *client = chip->client; u8 cmd; cmd = on ? TSL2563_CMD_POWER_ON : TSL2563_CMD_POWER_OFF; - return tsl2563_write(client, TSL2563_REG_CTRL, cmd); + return i2c_smbus_write_byte_data(client, + TSL2563_CMD | TSL2563_REG_CTRL, cmd); } /* @@ -178,36 +154,40 @@ static int tsl2563_get_power(struct tsl2563_chip *chip) { struct i2c_client *client = chip->client; int ret; - u8 val; - ret = tsl2563_read(client, TSL2563_REG_CTRL, &val, sizeof(val)); - if (ret != sizeof(val)) + ret = i2c_smbus_read_byte_data(client, TSL2563_CMD | TSL2563_REG_CTRL); + if (ret < 0) return ret; - return (val & TSL2563_CTRL_POWER_MASK) == TSL2563_CMD_POWER_ON; + return (ret & TSL2563_CTRL_POWER_MASK) == TSL2563_CMD_POWER_ON; } static int tsl2563_configure(struct tsl2563_chip *chip) { int ret; - ret = tsl2563_write(chip->client, TSL2563_REG_TIMING, + ret = i2c_smbus_write_byte_data(chip->client, + TSL2563_CMD | TSL2563_REG_TIMING, chip->gainlevel->gaintime); if (ret) goto error_ret; - ret = tsl2563_write(chip->client, TSL2563_REG_HIGHLOW, + ret = i2c_smbus_write_byte_data(chip->client, + TSL2563_CMD | TSL2563_REG_HIGHLOW, chip->high_thres & 0xFF); if (ret) goto error_ret; - ret = tsl2563_write(chip->client, TSL2563_REG_HIGHHIGH, + ret = i2c_smbus_write_byte_data(chip->client, + TSL2563_CMD | TSL2563_REG_HIGHHIGH, (chip->high_thres >> 8) & 0xFF); if (ret) goto error_ret; - ret = tsl2563_write(chip->client, TSL2563_REG_LOWLOW, + ret = i2c_smbus_write_byte_data(chip->client, + TSL2563_CMD | TSL2563_REG_LOWLOW, chip->low_thres & 0xFF); if (ret) goto error_ret; - ret = tsl2563_write(chip->client, TSL2563_REG_LOWHIGH, + ret = i2c_smbus_write_byte_data(chip->client, + TSL2563_CMD | TSL2563_REG_LOWHIGH, (chip->low_thres >> 8) & 0xFF); /* Interrupt register is automatically written anyway if it is relevant so is not here */ @@ -242,8 +222,8 @@ static int tsl2563_read_id(struct tsl2563_chip *chip, u8 *id) struct i2c_client *client = chip->client; int ret; - ret = tsl2563_read(client, TSL2563_REG_ID, id, sizeof(*id)); - if (ret != sizeof(*id)) + ret = i2c_smbus_read_byte_data(client, TSL2563_CMD | TSL2563_REG_ID); + if (ret < 0) return ret; return 0; @@ -313,8 +293,9 @@ static int tsl2563_adjust_gainlevel(struct tsl2563_chip *chip, u16 adc) (adc > chip->gainlevel->max) ? chip->gainlevel++ : chip->gainlevel--; - tsl2563_write(client, TSL2563_REG_TIMING, - chip->gainlevel->gaintime); + i2c_smbus_write_byte_data(client, + TSL2563_CMD | TSL2563_REG_TIMING, + chip->gainlevel->gaintime); tsl2563_wait_adc(chip); tsl2563_wait_adc(chip); @@ -327,7 +308,6 @@ static int tsl2563_adjust_gainlevel(struct tsl2563_chip *chip, u16 adc) static int tsl2563_get_adc(struct tsl2563_chip *chip) { struct i2c_client *client = chip->client; - u8 buf0[2], buf1[2]; u16 adc0, adc1; int retry = 1; int ret = 0; @@ -350,19 +330,17 @@ static int tsl2563_get_adc(struct tsl2563_chip *chip) } while (retry) { - ret = tsl2563_read(client, - TSL2563_REG_DATA0LOW, - buf0, sizeof(buf0)); - if (ret != sizeof(buf0)) + ret = i2c_smbus_read_word_data(client, + TSL2563_CMD | TSL2563_REG_DATA0LOW); + if (ret < 0) goto out; + adc0 = ret; - ret = tsl2563_read(client, TSL2563_REG_DATA1LOW, - buf1, sizeof(buf1)); - if (ret != sizeof(buf1)) + ret = i2c_smbus_read_word_data(client, + TSL2563_CMD | TSL2563_REG_DATA1LOW); + if (ret < 0) goto out; - - adc0 = (buf0[1] << 8) + buf0[0]; - adc1 = (buf1[1] << 8) + buf1[0]; + adc1 = ret; retry = tsl2563_adjust_gainlevel(chip, adc0); } @@ -540,7 +518,8 @@ static int tsl2563_read_raw(struct iio_dev *indio_dev, ret = IIO_VAL_INT; break; default: - return -EINVAL; + ret = -EINVAL; + goto error_ret; } error_ret: @@ -549,19 +528,30 @@ error_ret: } static const struct iio_chan_spec tsl2563_channels[] = { - IIO_CHAN(IIO_LIGHT, 0, 1, 1, NULL, 0, 0, 0, 0, 0, {}, 0), - IIO_CHAN(IIO_INTENSITY, 1, 1, 0, "both", 0, - (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE), 0, 0, 0, {}, - IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) | - IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING)), - IIO_CHAN(IIO_INTENSITY, 1, 1, 0, "ir", 1, - (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE), 0, 0, 0, {}, - 0) + { + .type = IIO_LIGHT, + .indexed = 1, + .channel = 0, + }, { + .type = IIO_INTENSITY, + .modified = 1, + .channel2 = IIO_MOD_LIGHT_BOTH, + .info_mask = (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE), + .event_mask = (IIO_EV_BIT(IIO_EV_TYPE_THRESH, + IIO_EV_DIR_RISING) | + IIO_EV_BIT(IIO_EV_TYPE_THRESH, + IIO_EV_DIR_FALLING)), + }, { + .type = IIO_INTENSITY, + .modified = 1, + .channel2 = IIO_MOD_LIGHT_BOTH, + .info_mask = (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE), + } }; static int tsl2563_read_thresh(struct iio_dev *indio_dev, - int event_code, - int *val) + u64 event_code, + int *val) { struct tsl2563_chip *chip = iio_priv(indio_dev); @@ -579,8 +569,8 @@ static int tsl2563_read_thresh(struct iio_dev *indio_dev, return 0; } -static ssize_t tsl2563_write_thresh(struct iio_dev *indio_dev, - int event_code, +static int tsl2563_write_thresh(struct iio_dev *indio_dev, + u64 event_code, int val) { struct tsl2563_chip *chip = iio_priv(indio_dev); @@ -592,11 +582,13 @@ static ssize_t tsl2563_write_thresh(struct iio_dev *indio_dev, else address = TSL2563_REG_LOWLOW; mutex_lock(&chip->lock); - ret = tsl2563_write(chip->client, address, val & 0xFF); + ret = i2c_smbus_write_byte_data(chip->client, TSL2563_CMD | address, + val & 0xFF); if (ret) goto error_ret; - ret = tsl2563_write(chip->client, address + 1, - (val >> 8) & 0xFF); + ret = i2c_smbus_write_byte_data(chip->client, + TSL2563_CMD | (address + 1), + (val >> 8) & 0xFF); if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_RISING) chip->high_thres = val; else @@ -612,23 +604,22 @@ static irqreturn_t tsl2563_event_handler(int irq, void *private) { struct iio_dev *dev_info = private; struct tsl2563_chip *chip = iio_priv(dev_info); - u8 cmd = TSL2563_CMD | TSL2563_CLEARINT; - iio_push_event(dev_info, 0, - IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_LIGHT, + iio_push_event(dev_info, + IIO_UNMOD_EVENT_CODE(IIO_LIGHT, 0, IIO_EV_TYPE_THRESH, IIO_EV_DIR_EITHER), iio_get_time_ns()); /* clear the interrupt and push the event */ - i2c_master_send(chip->client, &cmd, sizeof(cmd)); + i2c_smbus_write_byte(chip->client, TSL2563_CMD | TSL2563_CLEARINT); return IRQ_HANDLED; } static int tsl2563_write_interrupt_config(struct iio_dev *indio_dev, - int event_code, - int state) + u64 event_code, + int state) { struct tsl2563_chip *chip = iio_priv(indio_dev); int ret = 0; @@ -647,13 +638,17 @@ static int tsl2563_write_interrupt_config(struct iio_dev *indio_dev, if (ret) goto out; } - ret = tsl2563_write(chip->client, TSL2563_REG_INT, chip->intr); + ret = i2c_smbus_write_byte_data(chip->client, + TSL2563_CMD | TSL2563_REG_INT, + chip->intr); chip->int_enabled = true; } if (!state && (chip->intr & 0x30)) { chip->intr |= ~0x30; - ret = tsl2563_write(chip->client, TSL2563_REG_INT, chip->intr); + ret = i2c_smbus_write_byte_data(chip->client, + TSL2563_CMD | TSL2563_REG_INT, + chip->intr); chip->int_enabled = false; /* now the interrupt is not enabled, we can go to sleep */ schedule_delayed_work(&chip->poweroff_work, 5 * HZ); @@ -665,19 +660,18 @@ out: } static int tsl2563_read_interrupt_config(struct iio_dev *indio_dev, - int event_code) + u64 event_code) { struct tsl2563_chip *chip = iio_priv(indio_dev); - u8 rxbuf; int ret; mutex_lock(&chip->lock); - ret = tsl2563_read(chip->client, TSL2563_REG_INT, - &rxbuf, sizeof(rxbuf)); + ret = i2c_smbus_read_byte_data(chip->client, + TSL2563_CMD | TSL2563_REG_INT); mutex_unlock(&chip->lock); if (ret < 0) goto error_ret; - ret = !!(rxbuf & 0x30); + ret = !!(ret & 0x30); error_ret: return ret; @@ -690,11 +684,12 @@ static struct i2c_driver tsl2563_i2c_driver; static const struct iio_info tsl2563_info_no_irq = { .driver_module = THIS_MODULE, + .read_raw = &tsl2563_read_raw, + .write_raw = &tsl2563_write_raw, }; static const struct iio_info tsl2563_info = { .driver_module = THIS_MODULE, - .num_interrupt_lines = 1, .read_raw = &tsl2563_read_raw, .write_raw = &tsl2563_write_raw, .read_event_value = &tsl2563_read_thresh, @@ -711,7 +706,7 @@ static int __devinit tsl2563_probe(struct i2c_client *client, struct tsl2563_platform_data *pdata = client->dev.platform_data; int err = 0; int ret; - u8 id; + u8 id = 0; indio_dev = iio_allocate_device(sizeof(*chip)); if (!indio_dev) @@ -757,9 +752,6 @@ static int __devinit tsl2563_probe(struct i2c_client *client, indio_dev->info = &tsl2563_info; else indio_dev->info = &tsl2563_info_no_irq; - ret = iio_device_register(indio_dev); - if (ret) - goto fail1; if (client->irq) { ret = request_threaded_irq(client->irq, NULL, @@ -778,12 +770,16 @@ static int __devinit tsl2563_probe(struct i2c_client *client, /* The interrupt cannot yet be enabled so this is fine without lock */ schedule_delayed_work(&chip->poweroff_work, 5 * HZ); + ret = iio_device_register(indio_dev); + if (ret) + goto fail3; + return 0; fail3: if (client->irq) free_irq(client->irq, indio_dev); fail2: - iio_device_unregister(indio_dev); + iio_free_device(indio_dev); fail1: kfree(chip); return err; @@ -793,16 +789,20 @@ static int tsl2563_remove(struct i2c_client *client) { struct tsl2563_chip *chip = i2c_get_clientdata(client); struct iio_dev *indio_dev = iio_priv_to_dev(chip); + + iio_device_unregister(indio_dev); if (!chip->int_enabled) cancel_delayed_work(&chip->poweroff_work); /* Ensure that interrupts are disabled - then flush any bottom halves */ chip->intr |= ~0x30; - tsl2563_write(chip->client, TSL2563_REG_INT, chip->intr); + i2c_smbus_write_byte_data(chip->client, TSL2563_CMD | TSL2563_REG_INT, + chip->intr); flush_scheduled_work(); tsl2563_set_power(chip, 0); if (client->irq) free_irq(client->irq, indio_dev); - iio_device_unregister(indio_dev); + + iio_free_device(indio_dev); return 0; } diff --git a/drivers/staging/iio/light/tsl2583.c b/drivers/staging/iio/light/tsl2583.c index 5694610..80f77cf 100644 --- a/drivers/staging/iio/light/tsl2583.c +++ b/drivers/staging/iio/light/tsl2583.c @@ -27,6 +27,7 @@ #include <linux/mutex.h> #include <linux/unistd.h> #include <linux/slab.h> +#include <linux/module.h> #include "../iio.h" #define TSL258X_MAX_DEVICE_REGS 32 @@ -68,7 +69,7 @@ enum { TSL258X_CHIP_UNKNOWN = 0, TSL258X_CHIP_WORKING = 1, TSL258X_CHIP_SUSPENDED = 2 -} TSL258X_CHIP_WORKING_STATUS; +}; /* Per-device data */ struct taos_als_info { @@ -87,7 +88,6 @@ struct taos_settings { struct tsl2583_chip { struct mutex als_mutex; struct i2c_client *client; - struct iio_dev *iio_dev; struct taos_als_info als_cur_info; struct taos_settings taos_settings; int als_time_scale; @@ -114,7 +114,7 @@ struct taos_lux { /* This structure is intentionally large to accommodate updates via sysfs. */ /* Sized to 11 = max 10 segments + 1 termination segment */ /* Assumption is is one and only one type of glass used */ -struct taos_lux taos_device_lux[11] = { +static struct taos_lux taos_device_lux[11] = { { 9830, 8520, 15729 }, { 12452, 10807, 23344 }, { 14746, 6383, 11705 }, @@ -159,8 +159,7 @@ static void taos_defaults(struct tsl2583_chip *chip) static int taos_i2c_read(struct i2c_client *client, u8 reg, u8 *val, unsigned int len) { - int ret; - int i; + int i, ret; for (i = 0; i < len; i++) { /* select register to write */ @@ -191,47 +190,47 @@ taos_i2c_read(struct i2c_client *client, u8 reg, u8 *val, unsigned int len) * the array are then used along with the time scale factor array values, to * calculate the lux. */ -static int taos_get_lux(struct i2c_client *client) +static int taos_get_lux(struct iio_dev *indio_dev) { u16 ch0, ch1; /* separated ch0/ch1 data from device */ u32 lux; /* raw lux calculated from device data */ u32 ratio; u8 buf[5]; struct taos_lux *p; - struct tsl2583_chip *chip = i2c_get_clientdata(client); + struct tsl2583_chip *chip = iio_priv(indio_dev); int i, ret; u32 ch0lux = 0; u32 ch1lux = 0; if (mutex_trylock(&chip->als_mutex) == 0) { - dev_info(&client->dev, "taos_get_lux device is busy\n"); + dev_info(&chip->client->dev, "taos_get_lux device is busy\n"); return chip->als_cur_info.lux; /* busy, so return LAST VALUE */ } if (chip->taos_chip_status != TSL258X_CHIP_WORKING) { /* device is not enabled */ - dev_err(&client->dev, "taos_get_lux device is not enabled\n"); + dev_err(&chip->client->dev, "taos_get_lux device is not enabled\n"); ret = -EBUSY ; goto out_unlock; } - ret = taos_i2c_read(client, (TSL258X_CMD_REG), &buf[0], 1); + ret = taos_i2c_read(chip->client, (TSL258X_CMD_REG), &buf[0], 1); if (ret < 0) { - dev_err(&client->dev, "taos_get_lux failed to read CMD_REG\n"); + dev_err(&chip->client->dev, "taos_get_lux failed to read CMD_REG\n"); goto out_unlock; } /* is data new & valid */ if (!(buf[0] & TSL258X_STA_ADC_INTR)) { - dev_err(&client->dev, "taos_get_lux data not valid\n"); + dev_err(&chip->client->dev, "taos_get_lux data not valid\n"); ret = chip->als_cur_info.lux; /* return LAST VALUE */ goto out_unlock; } for (i = 0; i < 4; i++) { int reg = TSL258X_CMD_REG | (TSL258X_ALS_CHAN0LO + i); - ret = taos_i2c_read(client, reg, &buf[i], 1); + ret = taos_i2c_read(chip->client, reg, &buf[i], 1); if (ret < 0) { - dev_err(&client->dev, "taos_get_lux failed to read" + dev_err(&chip->client->dev, "taos_get_lux failed to read" " register %x\n", reg); goto out_unlock; } @@ -239,11 +238,12 @@ static int taos_get_lux(struct i2c_client *client) /* clear status, really interrupt status (interrupts are off), but * we use the bit anyway - don't forget 0x80 - this is a command*/ - ret = i2c_smbus_write_byte(client, - (TSL258X_CMD_REG | TSL258X_CMD_SPL_FN | TSL258X_CMD_ALS_INT_CLR)); + ret = i2c_smbus_write_byte(chip->client, + (TSL258X_CMD_REG | TSL258X_CMD_SPL_FN | + TSL258X_CMD_ALS_INT_CLR)); if (ret < 0) { - dev_err(&client->dev, + dev_err(&chip->client->dev, "taos_i2c_write_command failed in taos_get_lux, err = %d\n", ret); goto out_unlock; /* have no data, so return failure */ @@ -285,7 +285,7 @@ static int taos_get_lux(struct i2c_client *client) /* note: lux is 31 bit max at this point */ if (ch1lux > ch0lux) { - dev_dbg(&client->dev, "No Data - Return last value\n"); + dev_dbg(&chip->client->dev, "No Data - Return last value\n"); ret = chip->als_cur_info.lux = 0; goto out_unlock; } @@ -319,54 +319,56 @@ out_unlock: * to derive actual lux). * Return updated gain_trim value. */ -int taos_als_calibrate(struct i2c_client *client) +static int taos_als_calibrate(struct iio_dev *indio_dev) { - struct tsl2583_chip *chip = i2c_get_clientdata(client); + struct tsl2583_chip *chip = iio_priv(indio_dev); u8 reg_val; unsigned int gain_trim_val; int ret; int lux_val; - ret = i2c_smbus_write_byte(client, (TSL258X_CMD_REG | TSL258X_CNTRL)); + ret = i2c_smbus_write_byte(chip->client, + (TSL258X_CMD_REG | TSL258X_CNTRL)); if (ret < 0) { - dev_err(&client->dev, + dev_err(&chip->client->dev, "taos_als_calibrate failed to reach the CNTRL register, ret=%d\n", ret); return ret; } - reg_val = i2c_smbus_read_byte(client); + reg_val = i2c_smbus_read_byte(chip->client); if ((reg_val & (TSL258X_CNTL_ADC_ENBL | TSL258X_CNTL_PWR_ON)) != (TSL258X_CNTL_ADC_ENBL | TSL258X_CNTL_PWR_ON)) { - dev_err(&client->dev, + dev_err(&chip->client->dev, "taos_als_calibrate failed: device not powered on with ADC enabled\n"); return -1; } - ret = i2c_smbus_write_byte(client, (TSL258X_CMD_REG | TSL258X_CNTRL)); + ret = i2c_smbus_write_byte(chip->client, + (TSL258X_CMD_REG | TSL258X_CNTRL)); if (ret < 0) { - dev_err(&client->dev, + dev_err(&chip->client->dev, "taos_als_calibrate failed to reach the STATUS register, ret=%d\n", ret); return ret; } - reg_val = i2c_smbus_read_byte(client); + reg_val = i2c_smbus_read_byte(chip->client); if ((reg_val & TSL258X_STA_ADC_VALID) != TSL258X_STA_ADC_VALID) { - dev_err(&client->dev, + dev_err(&chip->client->dev, "taos_als_calibrate failed: STATUS - ADC not valid.\n"); return -ENODATA; } - lux_val = taos_get_lux(client); + lux_val = taos_get_lux(indio_dev); if (lux_val < 0) { - dev_err(&client->dev, "taos_als_calibrate failed to get lux\n"); + dev_err(&chip->client->dev, "taos_als_calibrate failed to get lux\n"); return lux_val; } gain_trim_val = (unsigned int) (((chip->taos_settings.als_cal_target) * chip->taos_settings.als_gain_trim) / lux_val); if ((gain_trim_val < 250) || (gain_trim_val > 4000)) { - dev_err(&client->dev, + dev_err(&chip->client->dev, "taos_als_calibrate failed: trim_val of %d is out of range\n", gain_trim_val); return -ENODATA; @@ -380,21 +382,21 @@ int taos_als_calibrate(struct i2c_client *client) * Turn the device on. * Configuration must be set before calling this function. */ -static int taos_chip_on(struct i2c_client *client) +static int taos_chip_on(struct iio_dev *indio_dev) { int i; - int ret = 0; + int ret; u8 *uP; u8 utmp; int als_count; int als_time; - struct tsl2583_chip *chip = i2c_get_clientdata(client); + struct tsl2583_chip *chip = iio_priv(indio_dev); /* and make sure we're not already on */ if (chip->taos_chip_status == TSL258X_CHIP_WORKING) { /* if forcing a register update - turn off, then on */ - dev_info(&client->dev, "device is already enabled\n"); - return -EINVAL; + dev_info(&chip->client->dev, "device is already enabled\n"); + return -EINVAL; } /* determine als integration regster */ @@ -416,20 +418,21 @@ static int taos_chip_on(struct i2c_client *client) /* TSL258x Specific power-on / adc enable sequence * Power on the device 1st. */ utmp = TSL258X_CNTL_PWR_ON; - ret = i2c_smbus_write_byte_data(client, - TSL258X_CMD_REG | TSL258X_CNTRL, utmp); + ret = i2c_smbus_write_byte_data(chip->client, + TSL258X_CMD_REG | TSL258X_CNTRL, utmp); if (ret < 0) { - dev_err(&client->dev, "taos_chip_on failed on CNTRL reg.\n"); + dev_err(&chip->client->dev, "taos_chip_on failed on CNTRL reg.\n"); return -1; } /* Use the following shadow copy for our delay before enabling ADC. * Write all the registers. */ for (i = 0, uP = chip->taos_config; i < TSL258X_REG_MAX; i++) { - ret = i2c_smbus_write_byte_data(client, TSL258X_CMD_REG + i, + ret = i2c_smbus_write_byte_data(chip->client, + TSL258X_CMD_REG + i, *uP++); if (ret < 0) { - dev_err(&client->dev, + dev_err(&chip->client->dev, "taos_chip_on failed on reg %d.\n", i); return -1; } @@ -439,10 +442,11 @@ static int taos_chip_on(struct i2c_client *client) /* NOW enable the ADC * initialize the desired mode of operation */ utmp = TSL258X_CNTL_PWR_ON | TSL258X_CNTL_ADC_ENBL; - ret = i2c_smbus_write_byte_data(client, TSL258X_CMD_REG | TSL258X_CNTRL, + ret = i2c_smbus_write_byte_data(chip->client, + TSL258X_CMD_REG | TSL258X_CNTRL, utmp); if (ret < 0) { - dev_err(&client->dev, "taos_chip_on failed on 2nd CTRL reg.\n"); + dev_err(&chip->client->dev, "taos_chip_on failed on 2nd CTRL reg.\n"); return -1; } chip->taos_chip_status = TSL258X_CHIP_WORKING; @@ -450,33 +454,26 @@ static int taos_chip_on(struct i2c_client *client) return ret; } -static int taos_chip_off(struct i2c_client *client) +static int taos_chip_off(struct iio_dev *indio_dev) { - struct tsl2583_chip *chip = i2c_get_clientdata(client); + struct tsl2583_chip *chip = iio_priv(indio_dev); int ret; /* turn device off */ chip->taos_chip_status = TSL258X_CHIP_SUSPENDED; - ret = i2c_smbus_write_byte_data(client, TSL258X_CMD_REG | TSL258X_CNTRL, + ret = i2c_smbus_write_byte_data(chip->client, + TSL258X_CMD_REG | TSL258X_CNTRL, 0x00); return ret; } /* Sysfs Interface Functions */ -static ssize_t taos_device_id(struct device *dev, -struct device_attribute *attr, char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct tsl2583_chip *chip = indio_dev->dev_data; - - return sprintf(buf, "%s\n", chip->client->name); -} static ssize_t taos_power_state_show(struct device *dev, struct device_attribute *attr, char *buf) { struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct tsl2583_chip *chip = indio_dev->dev_data; + struct tsl2583_chip *chip = iio_priv(indio_dev); return sprintf(buf, "%d\n", chip->taos_chip_status); } @@ -485,16 +482,15 @@ static ssize_t taos_power_state_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct tsl2583_chip *chip = indio_dev->dev_data; unsigned long value; if (strict_strtoul(buf, 0, &value)) return -EINVAL; if (value == 0) - taos_chip_off(chip->client); + taos_chip_off(indio_dev); else - taos_chip_on(chip->client); + taos_chip_on(indio_dev); return len; } @@ -503,7 +499,7 @@ static ssize_t taos_gain_show(struct device *dev, struct device_attribute *attr, char *buf) { struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct tsl2583_chip *chip = indio_dev->dev_data; + struct tsl2583_chip *chip = iio_priv(indio_dev); char gain[4] = {0}; switch (chip->taos_settings.als_gain) { @@ -528,7 +524,7 @@ static ssize_t taos_gain_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct tsl2583_chip *chip = indio_dev->dev_data; + struct tsl2583_chip *chip = iio_priv(indio_dev); unsigned long value; if (strict_strtoul(buf, 0, &value)) @@ -565,7 +561,7 @@ static ssize_t taos_als_time_show(struct device *dev, struct device_attribute *attr, char *buf) { struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct tsl2583_chip *chip = indio_dev->dev_data; + struct tsl2583_chip *chip = iio_priv(indio_dev); return sprintf(buf, "%d\n", chip->taos_settings.als_time); } @@ -574,7 +570,7 @@ static ssize_t taos_als_time_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct tsl2583_chip *chip = indio_dev->dev_data; + struct tsl2583_chip *chip = iio_priv(indio_dev); unsigned long value; if (strict_strtoul(buf, 0, &value)) @@ -586,7 +582,7 @@ static ssize_t taos_als_time_store(struct device *dev, if (value % 50) return -EINVAL; - chip->taos_settings.als_time = value; + chip->taos_settings.als_time = value; return len; } @@ -602,7 +598,7 @@ static ssize_t taos_als_trim_show(struct device *dev, struct device_attribute *attr, char *buf) { struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct tsl2583_chip *chip = indio_dev->dev_data; + struct tsl2583_chip *chip = iio_priv(indio_dev); return sprintf(buf, "%d\n", chip->taos_settings.als_gain_trim); } @@ -611,7 +607,7 @@ static ssize_t taos_als_trim_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct tsl2583_chip *chip = indio_dev->dev_data; + struct tsl2583_chip *chip = iio_priv(indio_dev); unsigned long value; if (strict_strtoul(buf, 0, &value)) @@ -627,7 +623,7 @@ static ssize_t taos_als_cal_target_show(struct device *dev, struct device_attribute *attr, char *buf) { struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct tsl2583_chip *chip = indio_dev->dev_data; + struct tsl2583_chip *chip = iio_priv(indio_dev); return sprintf(buf, "%d\n", chip->taos_settings.als_cal_target); } @@ -636,7 +632,7 @@ static ssize_t taos_als_cal_target_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct tsl2583_chip *chip = indio_dev->dev_data; + struct tsl2583_chip *chip = iio_priv(indio_dev); unsigned long value; if (strict_strtoul(buf, 0, &value)) @@ -651,27 +647,26 @@ static ssize_t taos_als_cal_target_store(struct device *dev, static ssize_t taos_lux_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct tsl2583_chip *chip = indio_dev->dev_data; - int lux; + int ret; - lux = taos_get_lux(chip->client); + ret = taos_get_lux(dev_get_drvdata(dev)); + if (ret < 0) + return ret; - return sprintf(buf, "%d\n", lux); + return sprintf(buf, "%d\n", ret); } static ssize_t taos_do_calibrate(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct tsl2583_chip *chip = indio_dev->dev_data; unsigned long value; if (strict_strtoul(buf, 0, &value)) return -EINVAL; if (value == 1) - taos_als_calibrate(chip->client); + taos_als_calibrate(indio_dev); return len; } @@ -703,8 +698,8 @@ static ssize_t taos_luxtable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct tsl2583_chip *chip = indio_dev->dev_data; - int value[ARRAY_SIZE(taos_device_lux)]; + struct tsl2583_chip *chip = iio_priv(indio_dev); + int value[ARRAY_SIZE(taos_device_lux)*3 + 1]; int n; get_options(buf, ARRAY_SIZE(value), value); @@ -725,18 +720,17 @@ static ssize_t taos_luxtable_store(struct device *dev, } if (chip->taos_chip_status == TSL258X_CHIP_WORKING) - taos_chip_off(chip->client); + taos_chip_off(indio_dev); /* Zero out the table */ memset(taos_device_lux, 0, sizeof(taos_device_lux)); memcpy(taos_device_lux, &value[1], (value[0] * 4)); - taos_chip_on(chip->client); + taos_chip_on(indio_dev); return len; } -static DEVICE_ATTR(name, S_IRUGO, taos_device_id, NULL); static DEVICE_ATTR(power_state, S_IRUGO | S_IWUSR, taos_power_state_show, taos_power_state_store); @@ -762,7 +756,6 @@ static DEVICE_ATTR(illuminance0_lux_table, S_IRUGO | S_IWUSR, taos_luxtable_show, taos_luxtable_store); static struct attribute *sysfs_attrs_ctrl[] = { - &dev_attr_name.attr, &dev_attr_power_state.attr, &dev_attr_illuminance0_calibscale.attr, /* Gain */ &dev_attr_illuminance0_calibscale_available.attr, @@ -798,9 +791,10 @@ static const struct iio_info tsl2583_info = { static int __devinit taos_probe(struct i2c_client *clientp, const struct i2c_device_id *idp) { - int i, ret = 0; + int i, ret; unsigned char buf[TSL258X_MAX_DEVICE_REGS]; - static struct tsl2583_chip *chip; + struct tsl2583_chip *chip; + struct iio_dev *indio_dev; if (!i2c_check_functionality(clientp->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { @@ -810,12 +804,15 @@ static int __devinit taos_probe(struct i2c_client *clientp, return -EOPNOTSUPP; } - chip = kzalloc(sizeof(struct tsl2583_chip), GFP_KERNEL); - if (!chip) - return -ENOMEM; - + indio_dev = iio_allocate_device(sizeof(*chip)); + if (indio_dev == NULL) { + ret = -ENOMEM; + dev_err(&clientp->dev, "iio allocation failed\n"); + goto fail1; + } + chip = iio_priv(indio_dev); chip->client = clientp; - i2c_set_clientdata(clientp, chip); + i2c_set_clientdata(clientp, indio_dev); mutex_init(&chip->als_mutex); chip->taos_chip_status = TSL258X_CHIP_UNKNOWN; @@ -827,14 +824,14 @@ static int __devinit taos_probe(struct i2c_client *clientp, if (ret < 0) { dev_err(&clientp->dev, "i2c_smbus_write_bytes() to cmd " "reg failed in taos_probe(), err = %d\n", ret); - goto fail1; + goto fail2; } ret = i2c_smbus_read_byte(clientp); if (ret < 0) { dev_err(&clientp->dev, "i2c_smbus_read_byte from " "reg failed in taos_probe(), err = %d\n", ret); - goto fail1; + goto fail2; } buf[i] = ret; } @@ -842,58 +839,50 @@ static int __devinit taos_probe(struct i2c_client *clientp, if (!taos_tsl258x_device(buf)) { dev_info(&clientp->dev, "i2c device found but does not match " "expected id in taos_probe()\n"); - goto fail1; + goto fail2; } ret = i2c_smbus_write_byte(clientp, (TSL258X_CMD_REG | TSL258X_CNTRL)); if (ret < 0) { dev_err(&clientp->dev, "i2c_smbus_write_byte() to cmd reg " "failed in taos_probe(), err = %d\n", ret); - goto fail1; - } - - chip->iio_dev = iio_allocate_device(0); - if (!chip->iio_dev) { - ret = -ENOMEM; - dev_err(&clientp->dev, "iio allocation failed\n"); - goto fail1; + goto fail2; } - chip->iio_dev->info = &tsl2583_info; - chip->iio_dev->dev.parent = &clientp->dev; - chip->iio_dev->dev_data = (void *)(chip); - chip->iio_dev->modes = INDIO_DIRECT_MODE; - ret = iio_device_register(chip->iio_dev); + indio_dev->info = &tsl2583_info; + indio_dev->dev.parent = &clientp->dev; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->name = chip->client->name; + ret = iio_device_register(indio_dev); if (ret) { dev_err(&clientp->dev, "iio registration failed\n"); - goto fail1; + goto fail2; } /* Load up the V2 defaults (these are hard coded defaults for now) */ taos_defaults(chip); /* Make sure the chip is on */ - taos_chip_on(clientp); + taos_chip_on(indio_dev); dev_info(&clientp->dev, "Light sensor found.\n"); - return 0; - fail1: - kfree(chip); - + iio_free_device(indio_dev); +fail2: return ret; } static int taos_suspend(struct i2c_client *client, pm_message_t state) { - struct tsl2583_chip *chip = i2c_get_clientdata(client); + struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct tsl2583_chip *chip = iio_priv(indio_dev); int ret = 0; mutex_lock(&chip->als_mutex); if (chip->taos_chip_status == TSL258X_CHIP_WORKING) { - ret = taos_chip_off(client); + ret = taos_chip_off(indio_dev); chip->taos_chip_status = TSL258X_CHIP_SUSPENDED; } @@ -903,13 +892,14 @@ static int taos_suspend(struct i2c_client *client, pm_message_t state) static int taos_resume(struct i2c_client *client) { - struct tsl2583_chip *chip = i2c_get_clientdata(client); + struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct tsl2583_chip *chip = iio_priv(indio_dev); int ret = 0; mutex_lock(&chip->als_mutex); if (chip->taos_chip_status == TSL258X_CHIP_SUSPENDED) - ret = taos_chip_on(client); + ret = taos_chip_on(indio_dev); mutex_unlock(&chip->als_mutex); return ret; @@ -918,11 +908,9 @@ static int taos_resume(struct i2c_client *client) static int __devexit taos_remove(struct i2c_client *client) { - struct tsl2583_chip *chip = i2c_get_clientdata(client); - - iio_device_unregister(chip->iio_dev); + iio_device_unregister(i2c_get_clientdata(client)); + iio_free_device(i2c_get_clientdata(client)); - kfree(chip); return 0; } |