staging: iio: isl29018: change isl29018_read_raw() to only have one exit point
[linux-2.6-block.git] / drivers / staging / iio / light / isl29018.c
index 76d9f74e7dcbfc9cfe6dd503f5e1bdf3bae37ba3..3a4d79d7e23c74fcc7438f465dcb8d1ffcaee53b 100644 (file)
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
 
 #include <linux/module.h>
 #include <linux/iio/sysfs.h>
 #include <linux/acpi.h>
 
-#define CONVERSION_TIME_MS             100
+#define ISL29018_CONV_TIME_MS          100
 
 #define ISL29018_REG_ADD_COMMAND1      0x00
-#define COMMMAND1_OPMODE_SHIFT         5
-#define COMMMAND1_OPMODE_MASK          (7 << COMMMAND1_OPMODE_SHIFT)
-#define COMMMAND1_OPMODE_POWER_DOWN    0
-#define COMMMAND1_OPMODE_ALS_ONCE      1
-#define COMMMAND1_OPMODE_IR_ONCE       2
-#define COMMMAND1_OPMODE_PROX_ONCE     3
+#define ISL29018_CMD1_OPMODE_SHIFT     5
+#define ISL29018_CMD1_OPMODE_MASK      (7 << ISL29018_CMD1_OPMODE_SHIFT)
+#define ISL29018_CMD1_OPMODE_POWER_DOWN        0
+#define ISL29018_CMD1_OPMODE_ALS_ONCE  1
+#define ISL29018_CMD1_OPMODE_IR_ONCE   2
+#define ISL29018_CMD1_OPMODE_PROX_ONCE 3
 
-#define ISL29018_REG_ADD_COMMANDII     0x01
-#define COMMANDII_RESOLUTION_SHIFT     2
-#define COMMANDII_RESOLUTION_MASK      (0x3 << COMMANDII_RESOLUTION_SHIFT)
+#define ISL29018_REG_ADD_COMMAND     0x01
+#define ISL29018_CMD2_RESOLUTION_SHIFT 2
+#define ISL29018_CMD2_RESOLUTION_MASK  (0x3 << ISL29018_CMD2_RESOLUTION_SHIFT)
 
-#define COMMANDII_RANGE_SHIFT          0
-#define COMMANDII_RANGE_MASK           (0x3 << COMMANDII_RANGE_SHIFT)
+#define ISL29018_CMD2_RANGE_SHIFT      0
+#define ISL29018_CMD2_RANGE_MASK       (0x3 << ISL29018_CMD2_RANGE_SHIFT)
 
-#define COMMANDII_SCHEME_SHIFT         7
-#define COMMANDII_SCHEME_MASK          (0x1 << COMMANDII_SCHEME_SHIFT)
+#define ISL29018_CMD2_SCHEME_SHIFT     7
+#define ISL29018_CMD2_SCHEME_MASK      (0x1 << ISL29018_CMD2_SCHEME_SHIFT)
 
 #define ISL29018_REG_ADD_DATA_LSB      0x02
 #define ISL29018_REG_ADD_DATA_MSB      0x03
 #define ISL29035_BOUT_SHIFT            0x07
 #define ISL29035_BOUT_MASK             (0x01 << ISL29035_BOUT_SHIFT)
 
-#define ISL29018_INT_TIME_AVAIL                "0.090000 0.005630 0.000351 0.000021"
-#define ISL29023_INT_TIME_AVAIL                "0.090000 0.005600 0.000352 0.000022"
-#define ISL29035_INT_TIME_AVAIL                "0.105000 0.006500 0.000410 0.000025"
-
-static const char * const int_time_avail[] = {
-       ISL29018_INT_TIME_AVAIL,
-       ISL29023_INT_TIME_AVAIL,
-       ISL29035_INT_TIME_AVAIL,
-};
-
 enum isl29018_int_time {
        ISL29018_INT_TIME_16,
        ISL29018_INT_TIME_12,
@@ -114,7 +100,8 @@ struct isl29018_chip {
 static int isl29018_set_integration_time(struct isl29018_chip *chip,
                                         unsigned int utime)
 {
-       int i, ret;
+       unsigned int i;
+       int ret;
        unsigned int int_time, new_int_time;
 
        for (i = 0; i < ARRAY_SIZE(isl29018_int_utimes[chip->type]); ++i) {
@@ -127,13 +114,13 @@ static int isl29018_set_integration_time(struct isl29018_chip *chip,
        if (i >= ARRAY_SIZE(isl29018_int_utimes[chip->type]))
                return -EINVAL;
 
-       ret = regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMANDII,
-                                COMMANDII_RESOLUTION_MASK,
-                                i << COMMANDII_RESOLUTION_SHIFT);
+       ret = regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMAND2,
+                                ISL29018_CMD2_RESOLUTION_MASK,
+                                i << ISL29018_CMD2_RESOLUTION_SHIFT);
        if (ret < 0)
                return ret;
 
-       /* keep the same range when integration time changes */
+       /* Keep the same range when integration time changes */
        int_time = chip->int_time;
        for (i = 0; i < ARRAY_SIZE(isl29018_scales[int_time]); ++i) {
                if (chip->scale.scale == isl29018_scales[int_time][i].scale &&
@@ -149,7 +136,8 @@ static int isl29018_set_integration_time(struct isl29018_chip *chip,
 
 static int isl29018_set_scale(struct isl29018_chip *chip, int scale, int uscale)
 {
-       int i, ret;
+       unsigned int i;
+       int ret;
        struct isl29018_scale new_scale;
 
        for (i = 0; i < ARRAY_SIZE(isl29018_scales[chip->int_time]); ++i) {
@@ -163,9 +151,9 @@ static int isl29018_set_scale(struct isl29018_chip *chip, int scale, int uscale)
        if (i >= ARRAY_SIZE(isl29018_scales[chip->int_time]))
                return -EINVAL;
 
-       ret = regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMANDII,
-                                COMMANDII_RANGE_MASK,
-                                i << COMMANDII_RANGE_SHIFT);
+       ret = regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMAND2,
+                                ISL29018_CMD2_RANGE_MASK,
+                                i << ISL29018_CMD2_RANGE_SHIFT);
        if (ret < 0)
                return ret;
 
@@ -183,13 +171,13 @@ static int isl29018_read_sensor_input(struct isl29018_chip *chip, int mode)
 
        /* Set mode */
        status = regmap_write(chip->regmap, ISL29018_REG_ADD_COMMAND1,
-                             mode << COMMMAND1_OPMODE_SHIFT);
+                             mode << ISL29018_CMD1_OPMODE_SHIFT);
        if (status) {
                dev_err(dev,
                        "Error in setting operating mode err %d\n", status);
                return status;
        }
-       msleep(CONVERSION_TIME_MS);
+       msleep(ISL29018_CONV_TIME_MS);
        status = regmap_read(chip->regmap, ISL29018_REG_ADD_DATA_LSB, &lsb);
        if (status < 0) {
                dev_err(dev,
@@ -213,8 +201,8 @@ static int isl29018_read_lux(struct isl29018_chip *chip, int *lux)
        int lux_data;
        unsigned int data_x_range;
 
-       lux_data = isl29018_read_sensor_input(chip, COMMMAND1_OPMODE_ALS_ONCE);
-
+       lux_data = isl29018_read_sensor_input(chip,
+                                             ISL29018_CMD1_OPMODE_ALS_ONCE);
        if (lux_data < 0)
                return lux_data;
 
@@ -230,8 +218,8 @@ static int isl29018_read_ir(struct isl29018_chip *chip, int *ir)
 {
        int ir_data;
 
-       ir_data = isl29018_read_sensor_input(chip, COMMMAND1_OPMODE_IR_ONCE);
-
+       ir_data = isl29018_read_sensor_input(chip,
+                                            ISL29018_CMD1_OPMODE_IR_ONCE);
        if (ir_data < 0)
                return ir_data;
 
@@ -249,16 +237,16 @@ static int isl29018_read_proximity_ir(struct isl29018_chip *chip, int scheme,
        struct device *dev = regmap_get_device(chip->regmap);
 
        /* Do proximity sensing with required scheme */
-       status = regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMANDII,
-                                   COMMANDII_SCHEME_MASK,
-                                   scheme << COMMANDII_SCHEME_SHIFT);
+       status = regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMAND2,
+                                   ISL29018_CMD2_SCHEME_MASK,
+                                   scheme << ISL29018_CMD2_SCHEME_SHIFT);
        if (status) {
                dev_err(dev, "Error in setting operating mode\n");
                return status;
        }
 
        prox_data = isl29018_read_sensor_input(chip,
-                                              COMMMAND1_OPMODE_PROX_ONCE);
+                                              ISL29018_CMD1_OPMODE_PROX_ONCE);
        if (prox_data < 0)
                return prox_data;
 
@@ -267,8 +255,8 @@ static int isl29018_read_proximity_ir(struct isl29018_chip *chip, int scheme,
                return 0;
        }
 
-       ir_data = isl29018_read_sensor_input(chip, COMMMAND1_OPMODE_IR_ONCE);
-
+       ir_data = isl29018_read_sensor_input(chip,
+                                            ISL29018_CMD1_OPMODE_IR_ONCE);
        if (ir_data < 0)
                return ir_data;
 
@@ -280,29 +268,35 @@ static int isl29018_read_proximity_ir(struct isl29018_chip *chip, int scheme,
        return 0;
 }
 
-static ssize_t show_scale_available(struct device *dev,
-                                   struct device_attribute *attr, char *buf)
+static ssize_t in_illuminance_scale_available_show
+                       (struct device *dev, struct device_attribute *attr,
+                        char *buf)
 {
        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
        struct isl29018_chip *chip = iio_priv(indio_dev);
-       int i, len = 0;
+       unsigned int i;
+       int len = 0;
 
+       mutex_lock(&chip->lock);
        for (i = 0; i < ARRAY_SIZE(isl29018_scales[chip->int_time]); ++i)
                len += sprintf(buf + len, "%d.%06d ",
                               isl29018_scales[chip->int_time][i].scale,
                               isl29018_scales[chip->int_time][i].uscale);
+       mutex_unlock(&chip->lock);
 
        buf[len - 1] = '\n';
 
        return len;
 }
 
-static ssize_t show_int_time_available(struct device *dev,
-                                      struct device_attribute *attr, char *buf)
+static ssize_t in_illuminance_integration_time_available_show
+                       (struct device *dev, struct device_attribute *attr,
+                        char *buf)
 {
        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
        struct isl29018_chip *chip = iio_priv(indio_dev);
-       int i, len = 0;
+       unsigned int i;
+       int len = 0;
 
        for (i = 0; i < ARRAY_SIZE(isl29018_int_utimes[chip->type]); ++i)
                len += sprintf(buf + len, "0.%06d ",
@@ -313,24 +307,23 @@ static ssize_t show_int_time_available(struct device *dev,
        return len;
 }
 
-/* proximity scheme */
-static ssize_t show_prox_infrared_suppression(struct device *dev,
-                                             struct device_attribute *attr,
-                                             char *buf)
+static ssize_t proximity_on_chip_ambient_infrared_suppression_show
+                       (struct device *dev, struct device_attribute *attr,
+                        char *buf)
 {
        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
        struct isl29018_chip *chip = iio_priv(indio_dev);
 
        /*
-        * return the "proximity scheme" i.e. if the chip does on chip
+        * Return the "proximity scheme" i.e. if the chip does on chip
         * infrared suppression (1 means perform on chip suppression)
         */
        return sprintf(buf, "%d\n", chip->prox_scheme);
 }
 
-static ssize_t store_prox_infrared_suppression(struct device *dev,
-                                              struct device_attribute *attr,
-                                              const char *buf, size_t count)
+static ssize_t proximity_on_chip_ambient_infrared_suppression_store
+                       (struct device *dev, struct device_attribute *attr,
+                        const char *buf, size_t count)
 {
        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
        struct isl29018_chip *chip = iio_priv(indio_dev);
@@ -338,13 +331,11 @@ static ssize_t store_prox_infrared_suppression(struct device *dev,
 
        if (kstrtoint(buf, 10, &val))
                return -EINVAL;
-       if (!(val == 0 || val == 1)) {
-               dev_err(dev, "The mode is not supported\n");
+       if (!(val == 0 || val == 1))
                return -EINVAL;
-       }
 
        /*
-        * get the  "proximity scheme" i.e. if the chip does on chip
+        * Get the "proximity scheme" i.e. if the chip does on chip
         * infrared suppression (1 means perform on chip suppression)
         */
        mutex_lock(&chip->lock);
@@ -354,7 +345,6 @@ static ssize_t store_prox_infrared_suppression(struct device *dev,
        return count;
 }
 
-/* Channel IO */
 static int isl29018_write_raw(struct iio_dev *indio_dev,
                              struct iio_chan_spec const *chan,
                              int val,
@@ -374,13 +364,8 @@ static int isl29018_write_raw(struct iio_dev *indio_dev,
                }
                break;
        case IIO_CHAN_INFO_INT_TIME:
-               if (chan->type == IIO_LIGHT) {
-                       if (val) {
-                               mutex_unlock(&chip->lock);
-                               return -EINVAL;
-                       }
+               if (chan->type == IIO_LIGHT && !val)
                        ret = isl29018_set_integration_time(chip, val2);
-               }
                break;
        case IIO_CHAN_INFO_SCALE:
                if (chan->type == IIO_LIGHT)
@@ -405,8 +390,8 @@ static int isl29018_read_raw(struct iio_dev *indio_dev,
 
        mutex_lock(&chip->lock);
        if (chip->suspended) {
-               mutex_unlock(&chip->lock);
-               return -EBUSY;
+               ret = -EBUSY;
+               goto read_done;
        }
        switch (mask) {
        case IIO_CHAN_INFO_RAW:
@@ -453,6 +438,8 @@ static int isl29018_read_raw(struct iio_dev *indio_dev,
        default:
                break;
        }
+
+read_done:
        mutex_unlock(&chip->lock);
        return ret;
 }
@@ -490,14 +477,9 @@ static const struct iio_chan_spec isl29023_channels[] = {
        ISL29018_IR_CHANNEL,
 };
 
-static IIO_DEVICE_ATTR(in_illuminance_integration_time_available, S_IRUGO,
-                      show_int_time_available, NULL, 0);
-static IIO_DEVICE_ATTR(in_illuminance_scale_available, S_IRUGO,
-                     show_scale_available, NULL, 0);
-static IIO_DEVICE_ATTR(proximity_on_chip_ambient_infrared_suppression,
-                                       S_IRUGO | S_IWUSR,
-                                       show_prox_infrared_suppression,
-                                       store_prox_infrared_suppression, 0);
+static IIO_DEVICE_ATTR_RO(in_illuminance_integration_time_available, 0);
+static IIO_DEVICE_ATTR_RO(in_illuminance_scale_available, 0);
+static IIO_DEVICE_ATTR_RW(proximity_on_chip_ambient_infrared_suppression, 0);
 
 #define ISL29018_DEV_ATTR(name) (&iio_dev_attr_##name.dev_attr.attr)
 
@@ -541,7 +523,7 @@ static int isl29035_detect(struct isl29018_chip *chip)
        if (id != ISL29035_DEVICE_ID)
                return -ENODEV;
 
-       /* clear out brownout bit */
+       /* Clear brownout bit */
        return regmap_update_bits(chip->regmap, ISL29035_REG_DEVICE_ID,
                                  ISL29035_BOUT_MASK, 0);
 }
@@ -574,7 +556,7 @@ static int isl29018_chip_init(struct isl29018_chip *chip)
         * conversions, clear the test registers, and then rewrite all
         * registers to the desired values.
         * ...
-        * FOR ISL29011, ISL29018, ISL29021, ISL29023
+        * 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
@@ -603,7 +585,7 @@ static int isl29018_chip_init(struct isl29018_chip *chip)
 
        usleep_range(1000, 2000);       /* per data sheet, page 10 */
 
-       /* set defaults */
+       /* Set defaults */
        status = isl29018_set_scale(chip, chip->scale.scale,
                                    chip->scale.uscale);
        if (status < 0) {
@@ -635,7 +617,7 @@ static const struct iio_info isl29023_info = {
        .write_raw = isl29018_write_raw,
 };
 
-static bool is_volatile_reg(struct device *dev, unsigned int reg)
+static bool isl29018_is_volatile_reg(struct device *dev, unsigned int reg)
 {
        switch (reg) {
        case ISL29018_REG_ADD_DATA_LSB:
@@ -649,37 +631,32 @@ static bool is_volatile_reg(struct device *dev, unsigned int reg)
        }
 }
 
-/*
- * isl29018_regmap_config: regmap configuration.
- * Use RBTREE mechanism for caching.
- */
 static const struct regmap_config isl29018_regmap_config = {
        .reg_bits = 8,
        .val_bits = 8,
-       .volatile_reg = is_volatile_reg,
+       .volatile_reg = isl29018_is_volatile_reg,
        .max_register = ISL29018_REG_TEST,
        .num_reg_defaults_raw = ISL29018_REG_TEST + 1,
        .cache_type = REGCACHE_RBTREE,
 };
 
-/* isl29035_regmap_config: regmap configuration for ISL29035 */
 static const struct regmap_config isl29035_regmap_config = {
        .reg_bits = 8,
        .val_bits = 8,
-       .volatile_reg = is_volatile_reg,
+       .volatile_reg = isl29018_is_volatile_reg,
        .max_register = ISL29035_REG_DEVICE_ID,
        .num_reg_defaults_raw = ISL29035_REG_DEVICE_ID + 1,
        .cache_type = REGCACHE_RBTREE,
 };
 
-struct chip_info {
+struct isl29018_chip_info {
        const struct iio_chan_spec *channels;
        int num_channels;
        const struct iio_info *indio_info;
        const struct regmap_config *regmap_cfg;
 };
 
-static const struct chip_info chip_info_tbl[] = {
+static const struct isl29018_chip_info isl29018_chip_info_tbl[] = {
        [isl29018] = {
                .channels = isl29018_channels,
                .num_channels = ARRAY_SIZE(isl29018_channels),
@@ -724,10 +701,8 @@ static int isl29018_probe(struct i2c_client *client,
        int dev_id = 0;
 
        indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip));
-       if (!indio_dev) {
-               dev_err(&client->dev, "iio allocation fails\n");
+       if (!indio_dev)
                return -ENOMEM;
-       }
        chip = iio_priv(indio_dev);
 
        i2c_set_clientdata(client, indio_dev);
@@ -750,7 +725,7 @@ static int isl29018_probe(struct i2c_client *client,
        chip->suspended = false;
 
        chip->regmap = devm_regmap_init_i2c(client,
-                               chip_info_tbl[dev_id].regmap_cfg);
+                               isl29018_chip_info_tbl[dev_id].regmap_cfg);
        if (IS_ERR(chip->regmap)) {
                err = PTR_ERR(chip->regmap);
                dev_err(&client->dev, "regmap initialization fails: %d\n", err);
@@ -761,19 +736,13 @@ static int isl29018_probe(struct i2c_client *client,
        if (err)
                return err;
 
-       indio_dev->info = chip_info_tbl[dev_id].indio_info;
-       indio_dev->channels = chip_info_tbl[dev_id].channels;
-       indio_dev->num_channels = chip_info_tbl[dev_id].num_channels;
+       indio_dev->info = isl29018_chip_info_tbl[dev_id].indio_info;
+       indio_dev->channels = isl29018_chip_info_tbl[dev_id].channels;
+       indio_dev->num_channels = isl29018_chip_info_tbl[dev_id].num_channels;
        indio_dev->name = name;
        indio_dev->dev.parent = &client->dev;
        indio_dev->modes = INDIO_DIRECT_MODE;
-       err = devm_iio_device_register(&client->dev, indio_dev);
-       if (err) {
-               dev_err(&client->dev, "iio registration fails\n");
-               return err;
-       }
-
-       return 0;
+       return devm_iio_device_register(&client->dev, indio_dev);
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -840,7 +809,6 @@ static const struct of_device_id isl29018_of_match[] = {
 MODULE_DEVICE_TABLE(of, isl29018_of_match);
 
 static struct i2c_driver isl29018_driver = {
-       .class  = I2C_CLASS_HWMON,
        .driver  = {
                        .name = "isl29018",
                        .acpi_match_table = ACPI_PTR(isl29018_acpi_match),