linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 0/2] staging: iio: isl29028: move out of staging
@ 2017-04-25  1:34 Brian Masney
  2017-04-25  1:34 ` [PATCH v3 1/2] staging: iio: isl29028: correct proximity sleep times Brian Masney
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Brian Masney @ 2017-04-25  1:34 UTC (permalink / raw)
  To: jic23, linux-iio
  Cc: gregkh, devel, knaack.h, lars, pmeerw, linux-kernel, ldewangan

Minor cleanup to the proximity sampling to move this driver out of
staging.

Datasheet:
http://www.intersil.com/content/dam/Intersil/documents/isl2/isl29028.pdf

Changes since v2:
- Reject any value that is not in the
  in_proximity_sampling_frequency_available sysfs attribute.
- Changed the sampling frequency 83.3 to 80. The data sheet lists 12.5
  ms, but the original code listed 12 ms, which was the cause of the
  discrepancy.
Changes since v1:
- in_proximity_sampling_frequency_available sysfs attribute now shows
  decimals.

Jonathan: Sorry it took me a little over two months to get back to you
on this driver. I got side tracked with other projects.

Brian Masney (2):
  staging: iio: isl29028: correct proximity sleep times
  staging: iio: isl29028: move out of staging

 drivers/iio/light/Kconfig            |  10 +
 drivers/iio/light/Makefile           |   1 +
 drivers/iio/light/isl29028.c         | 723 +++++++++++++++++++++++++++++++++++
 drivers/staging/iio/light/Kconfig    |  10 -
 drivers/staging/iio/light/Makefile   |   1 -
 drivers/staging/iio/light/isl29028.c | 693 ---------------------------------
 6 files changed, 734 insertions(+), 704 deletions(-)
 create mode 100644 drivers/iio/light/isl29028.c
 delete mode 100644 drivers/staging/iio/light/isl29028.c

-- 
2.9.3

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v3 1/2] staging: iio: isl29028: correct proximity sleep times
  2017-04-25  1:34 [PATCH v3 0/2] staging: iio: isl29028: move out of staging Brian Masney
@ 2017-04-25  1:34 ` Brian Masney
  2017-04-26  5:30   ` Jonathan Cameron
  2017-04-25  1:34 ` [PATCH v3 2/2] staging: iio: isl29028: move out of staging Brian Masney
  2017-04-26  5:25 ` [PATCH v3 0/2] " Jonathan Cameron
  2 siblings, 1 reply; 8+ messages in thread
From: Brian Masney @ 2017-04-25  1:34 UTC (permalink / raw)
  To: jic23, linux-iio
  Cc: gregkh, devel, knaack.h, lars, pmeerw, linux-kernel, ldewangan

The sysfs attribute in_proximity_sampling_frequency_available currently
shows the values 1 3 5 10 13 20 83 100. These values are supposed to
correspond to the sleep values 800 400 200 100 75 50 12.5 0 (all in ms).
When passing in a sampling frequency of 3, it actually uses a sleep
time of 200ms instead of the expected 400ms value. This patch changes
the value shown by this sysfs attribute to use fixed-point numbers so
that the correct sampling frequency is shown to the user. This patch
also changes the code that updates the proximity sampling frequency to
only allow values that are shown in the _available sysfs attribute.

The original code showed the value 83 that corresponds to the sleep
time 12 ms. The data sheet actually lists 12.5 ms as the sleep time,
so the proximity frequency was updated to 80.

Signed-off-by: Brian Masney <masneyb@onstation.org>
---
 drivers/staging/iio/light/isl29028.c | 70 +++++++++++++++++++++++++-----------
 1 file changed, 50 insertions(+), 20 deletions(-)

diff --git a/drivers/staging/iio/light/isl29028.c b/drivers/staging/iio/light/isl29028.c
index 5375e7a..aeb5082 100644
--- a/drivers/staging/iio/light/isl29028.c
+++ b/drivers/staging/iio/light/isl29028.c
@@ -64,8 +64,25 @@
 
 #define ISL29028_POWER_OFF_DELAY_MS		2000
 
-static const unsigned int isl29028_prox_sleep_time[] = {800, 400, 200, 100, 75,
-							50, 12, 0};
+struct isl29028_prox_data {
+	int sampling_int;
+	int sampling_fract;
+	int sleep_time;
+};
+
+static const struct isl29028_prox_data isl29028_prox_data[] = {
+	{   1, 250000, 800 },
+	{   2, 500000, 400 },
+	{   5,      0, 200 },
+	{  10,      0, 100 },
+	{  13, 300000,  75 },
+	{  20,      0,  50 },
+	{  80,      0,  13 }, /*
+			       * Note: Data sheet lists 12.5 ms sleep time.
+			       * Round up a half millisecond for msleep().
+			       */
+	{ 100,  0,   0 }
+};
 
 enum isl29028_als_ir_mode {
 	ISL29028_MODE_NONE = 0,
@@ -76,32 +93,37 @@ enum isl29028_als_ir_mode {
 struct isl29028_chip {
 	struct mutex			lock;
 	struct regmap			*regmap;
-	unsigned int			prox_sampling;
+	int				prox_sampling_int;
+	int				prox_sampling_frac;
 	bool				enable_prox;
 	int				lux_scale;
 	enum isl29028_als_ir_mode	als_ir_mode;
 };
 
-static int isl29028_find_prox_sleep_time_index(int sampling)
+static int isl29028_find_prox_sleep_index(int sampling_int, int sampling_fract)
 {
-	unsigned int period = DIV_ROUND_UP(1000, sampling);
 	int i;
 
-	for (i = 0; i < ARRAY_SIZE(isl29028_prox_sleep_time); ++i) {
-		if (period >= isl29028_prox_sleep_time[i])
-			break;
+	for (i = 0; i < ARRAY_SIZE(isl29028_prox_data); ++i) {
+		if (isl29028_prox_data[i].sampling_int == sampling_int &&
+		    isl29028_prox_data[i].sampling_fract == sampling_fract)
+			return i;
 	}
 
-	return i;
+	return -EINVAL;
 }
 
 static int isl29028_set_proxim_sampling(struct isl29028_chip *chip,
-					unsigned int sampling)
+					int sampling_int, int sampling_fract)
 {
 	struct device *dev = regmap_get_device(chip->regmap);
 	int sleep_index, ret;
 
-	sleep_index = isl29028_find_prox_sleep_time_index(sampling);
+	sleep_index = isl29028_find_prox_sleep_index(sampling_int,
+						     sampling_fract);
+	if (sleep_index < 0)
+		return sleep_index;
+
 	ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
 				 ISL29028_CONF_PROX_SLP_MASK,
 				 sleep_index << ISL29028_CONF_PROX_SLP_SH);
@@ -112,16 +134,18 @@ static int isl29028_set_proxim_sampling(struct isl29028_chip *chip,
 		return ret;
 	}
 
-	chip->prox_sampling = sampling;
+	chip->prox_sampling_int = sampling_int;
+	chip->prox_sampling_frac = sampling_fract;
 
 	return ret;
 }
 
 static int isl29028_enable_proximity(struct isl29028_chip *chip)
 {
-	int sleep_index, ret;
+	int prox_index, ret;
 
-	ret = isl29028_set_proxim_sampling(chip, chip->prox_sampling);
+	ret = isl29028_set_proxim_sampling(chip, chip->prox_sampling_int,
+					   chip->prox_sampling_frac);
 	if (ret < 0)
 		return ret;
 
@@ -132,8 +156,12 @@ static int isl29028_enable_proximity(struct isl29028_chip *chip)
 		return ret;
 
 	/* Wait for conversion to be complete for first sample */
-	sleep_index = isl29028_find_prox_sleep_time_index(chip->prox_sampling);
-	msleep(isl29028_prox_sleep_time[sleep_index]);
+	prox_index = isl29028_find_prox_sleep_index(chip->prox_sampling_int,
+						    chip->prox_sampling_frac);
+	if (prox_index < 0)
+		return prox_index;
+
+	msleep(isl29028_prox_data[prox_index].sleep_time);
 
 	return 0;
 }
@@ -361,7 +389,7 @@ static int isl29028_write_raw(struct iio_dev *indio_dev,
 			break;
 		}
 
-		ret = isl29028_set_proxim_sampling(chip, val);
+		ret = isl29028_set_proxim_sampling(chip, val, val2);
 		break;
 	case IIO_LIGHT:
 		if (mask != IIO_CHAN_INFO_SCALE) {
@@ -439,7 +467,8 @@ static int isl29028_read_raw(struct iio_dev *indio_dev,
 		if (chan->type != IIO_PROXIMITY)
 			break;
 
-		*val = chip->prox_sampling;
+		*val = chip->prox_sampling_int;
+		*val2 = chip->prox_sampling_frac;
 		ret = IIO_VAL_INT;
 		break;
 	case IIO_CHAN_INFO_SCALE:
@@ -472,7 +501,7 @@ static int isl29028_read_raw(struct iio_dev *indio_dev,
 }
 
 static IIO_CONST_ATTR(in_proximity_sampling_frequency_available,
-				"1 3 5 10 13 20 83 100");
+				"1.25 2.5 5 10 13.3 20 80 100");
 static IIO_CONST_ATTR(in_illuminance_scale_available, "125 2000");
 
 #define ISL29028_CONST_ATTR(name) (&iio_const_attr_##name.dev_attr.attr)
@@ -571,7 +600,8 @@ static int isl29028_probe(struct i2c_client *client,
 	}
 
 	chip->enable_prox  = false;
-	chip->prox_sampling = 20;
+	chip->prox_sampling_int = 20;
+	chip->prox_sampling_frac = 0;
 	chip->lux_scale = 2000;
 
 	ret = regmap_write(chip->regmap, ISL29028_REG_TEST1_MODE, 0x0);
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v3 2/2] staging: iio: isl29028: move out of staging
  2017-04-25  1:34 [PATCH v3 0/2] staging: iio: isl29028: move out of staging Brian Masney
  2017-04-25  1:34 ` [PATCH v3 1/2] staging: iio: isl29028: correct proximity sleep times Brian Masney
@ 2017-04-25  1:34 ` Brian Masney
  2017-04-26  5:30   ` Jonathan Cameron
  2017-04-26  5:25 ` [PATCH v3 0/2] " Jonathan Cameron
  2 siblings, 1 reply; 8+ messages in thread
From: Brian Masney @ 2017-04-25  1:34 UTC (permalink / raw)
  To: jic23, linux-iio
  Cc: gregkh, devel, knaack.h, lars, pmeerw, linux-kernel, ldewangan

Move ISL29028 ALS / Proximity Sensor out of staging and into mainline.

Signed-off-by: Brian Masney <masneyb@onstation.org>
---
 drivers/iio/light/Kconfig            |  10 +
 drivers/iio/light/Makefile           |   1 +
 drivers/iio/light/isl29028.c         | 723 +++++++++++++++++++++++++++++++++++
 drivers/staging/iio/light/Kconfig    |  10 -
 drivers/staging/iio/light/Makefile   |   1 -
 drivers/staging/iio/light/isl29028.c | 723 -----------------------------------
 6 files changed, 734 insertions(+), 734 deletions(-)
 create mode 100644 drivers/iio/light/isl29028.c
 delete mode 100644 drivers/staging/iio/light/isl29028.c

diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig
index 33e755d..2356ed9 100644
--- a/drivers/iio/light/Kconfig
+++ b/drivers/iio/light/Kconfig
@@ -172,6 +172,16 @@ config SENSORS_ISL29018
 	 in lux, proximity infrared sensing and normal infrared sensing.
 	 Data from sensor is accessible via sysfs.
 
+config SENSORS_ISL29028
+	tristate "Intersil ISL29028 Concurrent Light and Proximity Sensor"
+	depends on I2C
+	select REGMAP_I2C
+	help
+	 Provides driver for the Intersil's ISL29028 device.
+	 This driver supports the sysfs interface to get the ALS, IR intensity,
+	 Proximity value via iio. The ISL29028 provides the concurrent sensing
+	 of ambient light and proximity.
+
 config ISL29125
 	tristate "Intersil ISL29125 digital color light sensor"
 	depends on I2C
diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile
index 681363c..fa32fa4 100644
--- a/drivers/iio/light/Makefile
+++ b/drivers/iio/light/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_GP2AP020A00F)	+= gp2ap020a00f.o
 obj-$(CONFIG_HID_SENSOR_ALS)	+= hid-sensor-als.o
 obj-$(CONFIG_HID_SENSOR_PROX)	+= hid-sensor-prox.o
 obj-$(CONFIG_SENSORS_ISL29018)	+= isl29018.o
+obj-$(CONFIG_SENSORS_ISL29028)	+= isl29028.o
 obj-$(CONFIG_ISL29125)		+= isl29125.o
 obj-$(CONFIG_JSA1212)		+= jsa1212.o
 obj-$(CONFIG_SENSORS_LM3533)	+= lm3533-als.o
diff --git a/drivers/iio/light/isl29028.c b/drivers/iio/light/isl29028.c
new file mode 100644
index 0000000..aeb5082
--- /dev/null
+++ b/drivers/iio/light/isl29028.c
@@ -0,0 +1,723 @@
+/*
+ * IIO driver for the light sensor ISL29028.
+ * ISL29028 is Concurrent Ambient Light and Proximity Sensor
+ *
+ * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2016-2017 Brian Masney <masneyb@onstation.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/regmap.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/pm_runtime.h>
+
+#define ISL29028_CONV_TIME_MS			100
+
+#define ISL29028_REG_CONFIGURE			0x01
+
+#define ISL29028_CONF_ALS_IR_MODE_ALS		0
+#define ISL29028_CONF_ALS_IR_MODE_IR		BIT(0)
+#define ISL29028_CONF_ALS_IR_MODE_MASK		BIT(0)
+
+#define ISL29028_CONF_ALS_RANGE_LOW_LUX		0
+#define ISL29028_CONF_ALS_RANGE_HIGH_LUX	BIT(1)
+#define ISL29028_CONF_ALS_RANGE_MASK		BIT(1)
+
+#define ISL29028_CONF_ALS_DIS			0
+#define ISL29028_CONF_ALS_EN			BIT(2)
+#define ISL29028_CONF_ALS_EN_MASK		BIT(2)
+
+#define ISL29028_CONF_PROX_SLP_SH		4
+#define ISL29028_CONF_PROX_SLP_MASK		(7 << ISL29028_CONF_PROX_SLP_SH)
+
+#define ISL29028_CONF_PROX_EN			BIT(7)
+#define ISL29028_CONF_PROX_EN_MASK		BIT(7)
+
+#define ISL29028_REG_INTERRUPT			0x02
+
+#define ISL29028_REG_PROX_DATA			0x08
+#define ISL29028_REG_ALSIR_L			0x09
+#define ISL29028_REG_ALSIR_U			0x0A
+
+#define ISL29028_REG_TEST1_MODE			0x0E
+#define ISL29028_REG_TEST2_MODE			0x0F
+
+#define ISL29028_NUM_REGS			(ISL29028_REG_TEST2_MODE + 1)
+
+#define ISL29028_POWER_OFF_DELAY_MS		2000
+
+struct isl29028_prox_data {
+	int sampling_int;
+	int sampling_fract;
+	int sleep_time;
+};
+
+static const struct isl29028_prox_data isl29028_prox_data[] = {
+	{   1, 250000, 800 },
+	{   2, 500000, 400 },
+	{   5,      0, 200 },
+	{  10,      0, 100 },
+	{  13, 300000,  75 },
+	{  20,      0,  50 },
+	{  80,      0,  13 }, /*
+			       * Note: Data sheet lists 12.5 ms sleep time.
+			       * Round up a half millisecond for msleep().
+			       */
+	{ 100,  0,   0 }
+};
+
+enum isl29028_als_ir_mode {
+	ISL29028_MODE_NONE = 0,
+	ISL29028_MODE_ALS,
+	ISL29028_MODE_IR,
+};
+
+struct isl29028_chip {
+	struct mutex			lock;
+	struct regmap			*regmap;
+	int				prox_sampling_int;
+	int				prox_sampling_frac;
+	bool				enable_prox;
+	int				lux_scale;
+	enum isl29028_als_ir_mode	als_ir_mode;
+};
+
+static int isl29028_find_prox_sleep_index(int sampling_int, int sampling_fract)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(isl29028_prox_data); ++i) {
+		if (isl29028_prox_data[i].sampling_int == sampling_int &&
+		    isl29028_prox_data[i].sampling_fract == sampling_fract)
+			return i;
+	}
+
+	return -EINVAL;
+}
+
+static int isl29028_set_proxim_sampling(struct isl29028_chip *chip,
+					int sampling_int, int sampling_fract)
+{
+	struct device *dev = regmap_get_device(chip->regmap);
+	int sleep_index, ret;
+
+	sleep_index = isl29028_find_prox_sleep_index(sampling_int,
+						     sampling_fract);
+	if (sleep_index < 0)
+		return sleep_index;
+
+	ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
+				 ISL29028_CONF_PROX_SLP_MASK,
+				 sleep_index << ISL29028_CONF_PROX_SLP_SH);
+
+	if (ret < 0) {
+		dev_err(dev, "%s(): Error %d setting the proximity sampling\n",
+			__func__, ret);
+		return ret;
+	}
+
+	chip->prox_sampling_int = sampling_int;
+	chip->prox_sampling_frac = sampling_fract;
+
+	return ret;
+}
+
+static int isl29028_enable_proximity(struct isl29028_chip *chip)
+{
+	int prox_index, ret;
+
+	ret = isl29028_set_proxim_sampling(chip, chip->prox_sampling_int,
+					   chip->prox_sampling_frac);
+	if (ret < 0)
+		return ret;
+
+	ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
+				 ISL29028_CONF_PROX_EN_MASK,
+				 ISL29028_CONF_PROX_EN);
+	if (ret < 0)
+		return ret;
+
+	/* Wait for conversion to be complete for first sample */
+	prox_index = isl29028_find_prox_sleep_index(chip->prox_sampling_int,
+						    chip->prox_sampling_frac);
+	if (prox_index < 0)
+		return prox_index;
+
+	msleep(isl29028_prox_data[prox_index].sleep_time);
+
+	return 0;
+}
+
+static int isl29028_set_als_scale(struct isl29028_chip *chip, int lux_scale)
+{
+	struct device *dev = regmap_get_device(chip->regmap);
+	int val = (lux_scale == 2000) ? ISL29028_CONF_ALS_RANGE_HIGH_LUX :
+					ISL29028_CONF_ALS_RANGE_LOW_LUX;
+	int ret;
+
+	ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
+				 ISL29028_CONF_ALS_RANGE_MASK, val);
+	if (ret < 0) {
+		dev_err(dev, "%s(): Error %d setting the ALS scale\n", __func__,
+			ret);
+		return ret;
+	}
+
+	chip->lux_scale = lux_scale;
+
+	return ret;
+}
+
+static int isl29028_set_als_ir_mode(struct isl29028_chip *chip,
+				    enum isl29028_als_ir_mode mode)
+{
+	int ret;
+
+	if (chip->als_ir_mode == mode)
+		return 0;
+
+	ret = isl29028_set_als_scale(chip, chip->lux_scale);
+	if (ret < 0)
+		return ret;
+
+	switch (mode) {
+	case ISL29028_MODE_ALS:
+		ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
+					 ISL29028_CONF_ALS_IR_MODE_MASK,
+					 ISL29028_CONF_ALS_IR_MODE_ALS);
+		if (ret < 0)
+			return ret;
+
+		ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
+					 ISL29028_CONF_ALS_RANGE_MASK,
+					 ISL29028_CONF_ALS_RANGE_HIGH_LUX);
+		break;
+	case ISL29028_MODE_IR:
+		ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
+					 ISL29028_CONF_ALS_IR_MODE_MASK,
+					 ISL29028_CONF_ALS_IR_MODE_IR);
+		break;
+	case ISL29028_MODE_NONE:
+		return regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
+					  ISL29028_CONF_ALS_EN_MASK,
+					  ISL29028_CONF_ALS_DIS);
+	}
+
+	if (ret < 0)
+		return ret;
+
+	/* Enable the ALS/IR */
+	ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
+				 ISL29028_CONF_ALS_EN_MASK,
+				 ISL29028_CONF_ALS_EN);
+	if (ret < 0)
+		return ret;
+
+	/* Need to wait for conversion time if ALS/IR mode enabled */
+	msleep(ISL29028_CONV_TIME_MS);
+
+	chip->als_ir_mode = mode;
+
+	return 0;
+}
+
+static int isl29028_read_als_ir(struct isl29028_chip *chip, int *als_ir)
+{
+	struct device *dev = regmap_get_device(chip->regmap);
+	unsigned int lsb;
+	unsigned int msb;
+	int ret;
+
+	ret = regmap_read(chip->regmap, ISL29028_REG_ALSIR_L, &lsb);
+	if (ret < 0) {
+		dev_err(dev,
+			"%s(): Error %d reading register ALSIR_L\n",
+			__func__, ret);
+		return ret;
+	}
+
+	ret = regmap_read(chip->regmap, ISL29028_REG_ALSIR_U, &msb);
+	if (ret < 0) {
+		dev_err(dev,
+			"%s(): Error %d reading register ALSIR_U\n",
+			__func__, ret);
+		return ret;
+	}
+
+	*als_ir = ((msb & 0xF) << 8) | (lsb & 0xFF);
+
+	return 0;
+}
+
+static int isl29028_read_proxim(struct isl29028_chip *chip, int *prox)
+{
+	struct device *dev = regmap_get_device(chip->regmap);
+	unsigned int data;
+	int ret;
+
+	if (!chip->enable_prox) {
+		ret = isl29028_enable_proximity(chip);
+		if (ret < 0)
+			return ret;
+
+		chip->enable_prox = true;
+	}
+
+	ret = regmap_read(chip->regmap, ISL29028_REG_PROX_DATA, &data);
+	if (ret < 0) {
+		dev_err(dev, "%s(): Error %d reading register PROX_DATA\n",
+			__func__, ret);
+		return ret;
+	}
+
+	*prox = data;
+
+	return 0;
+}
+
+static int isl29028_als_get(struct isl29028_chip *chip, int *als_data)
+{
+	struct device *dev = regmap_get_device(chip->regmap);
+	int ret;
+	int als_ir_data;
+
+	ret = isl29028_set_als_ir_mode(chip, ISL29028_MODE_ALS);
+	if (ret < 0) {
+		dev_err(dev, "%s(): Error %d enabling ALS mode\n", __func__,
+			ret);
+		return ret;
+	}
+
+	ret = isl29028_read_als_ir(chip, &als_ir_data);
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * convert als data count to lux.
+	 * if lux_scale = 125,  lux = count * 0.031
+	 * if lux_scale = 2000, lux = count * 0.49
+	 */
+	if (chip->lux_scale == 125)
+		als_ir_data = (als_ir_data * 31) / 1000;
+	else
+		als_ir_data = (als_ir_data * 49) / 100;
+
+	*als_data = als_ir_data;
+
+	return 0;
+}
+
+static int isl29028_ir_get(struct isl29028_chip *chip, int *ir_data)
+{
+	struct device *dev = regmap_get_device(chip->regmap);
+	int ret;
+
+	ret = isl29028_set_als_ir_mode(chip, ISL29028_MODE_IR);
+	if (ret < 0) {
+		dev_err(dev, "%s(): Error %d enabling IR mode\n", __func__,
+			ret);
+		return ret;
+	}
+
+	return isl29028_read_als_ir(chip, ir_data);
+}
+
+static int isl29028_set_pm_runtime_busy(struct isl29028_chip *chip, bool on)
+{
+	struct device *dev = regmap_get_device(chip->regmap);
+	int ret;
+
+	if (on) {
+		ret = pm_runtime_get_sync(dev);
+		if (ret < 0)
+			pm_runtime_put_noidle(dev);
+	} else {
+		pm_runtime_mark_last_busy(dev);
+		ret = pm_runtime_put_autosuspend(dev);
+	}
+
+	return ret;
+}
+
+/* Channel IO */
+static int isl29028_write_raw(struct iio_dev *indio_dev,
+			      struct iio_chan_spec const *chan,
+			      int val, int val2, long mask)
+{
+	struct isl29028_chip *chip = iio_priv(indio_dev);
+	struct device *dev = regmap_get_device(chip->regmap);
+	int ret;
+
+	ret = isl29028_set_pm_runtime_busy(chip, true);
+	if (ret < 0)
+		return ret;
+
+	mutex_lock(&chip->lock);
+
+	ret = -EINVAL;
+	switch (chan->type) {
+	case IIO_PROXIMITY:
+		if (mask != IIO_CHAN_INFO_SAMP_FREQ) {
+			dev_err(dev,
+				"%s(): proximity: Mask value 0x%08lx is not supported\n",
+				__func__, mask);
+			break;
+		}
+
+		if (val < 1 || val > 100) {
+			dev_err(dev,
+				"%s(): proximity: Sampling frequency %d is not in the range [1:100]\n",
+				__func__, val);
+			break;
+		}
+
+		ret = isl29028_set_proxim_sampling(chip, val, val2);
+		break;
+	case IIO_LIGHT:
+		if (mask != IIO_CHAN_INFO_SCALE) {
+			dev_err(dev,
+				"%s(): light: Mask value 0x%08lx is not supported\n",
+				__func__, mask);
+			break;
+		}
+
+		if (val != 125 && val != 2000) {
+			dev_err(dev,
+				"%s(): light: Lux scale %d is not in the set {125, 2000}\n",
+				__func__, val);
+			break;
+		}
+
+		ret = isl29028_set_als_scale(chip, val);
+		break;
+	default:
+		dev_err(dev, "%s(): Unsupported channel type %x\n",
+			__func__, chan->type);
+		break;
+	}
+
+	mutex_unlock(&chip->lock);
+
+	if (ret < 0)
+		return ret;
+
+	ret = isl29028_set_pm_runtime_busy(chip, false);
+	if (ret < 0)
+		return ret;
+
+	return ret;
+}
+
+static int isl29028_read_raw(struct iio_dev *indio_dev,
+			     struct iio_chan_spec const *chan,
+			     int *val, int *val2, long mask)
+{
+	struct isl29028_chip *chip = iio_priv(indio_dev);
+	struct device *dev = regmap_get_device(chip->regmap);
+	int ret, pm_ret;
+
+	ret = isl29028_set_pm_runtime_busy(chip, true);
+	if (ret < 0)
+		return ret;
+
+	mutex_lock(&chip->lock);
+
+	ret = -EINVAL;
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+	case IIO_CHAN_INFO_PROCESSED:
+		switch (chan->type) {
+		case IIO_LIGHT:
+			ret = isl29028_als_get(chip, val);
+			break;
+		case IIO_INTENSITY:
+			ret = isl29028_ir_get(chip, val);
+			break;
+		case IIO_PROXIMITY:
+			ret = isl29028_read_proxim(chip, val);
+			break;
+		default:
+			break;
+		}
+
+		if (ret < 0)
+			break;
+
+		ret = IIO_VAL_INT;
+		break;
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		if (chan->type != IIO_PROXIMITY)
+			break;
+
+		*val = chip->prox_sampling_int;
+		*val2 = chip->prox_sampling_frac;
+		ret = IIO_VAL_INT;
+		break;
+	case IIO_CHAN_INFO_SCALE:
+		if (chan->type != IIO_LIGHT)
+			break;
+		*val = chip->lux_scale;
+		ret = IIO_VAL_INT;
+		break;
+	default:
+		dev_err(dev, "%s(): mask value 0x%08lx is not supported\n",
+			__func__, mask);
+		break;
+	}
+
+	mutex_unlock(&chip->lock);
+
+	if (ret < 0)
+		return ret;
+
+	/**
+	 * Preserve the ret variable if the call to
+	 * isl29028_set_pm_runtime_busy() is successful so the reading
+	 * (if applicable) is returned to user space.
+	 */
+	pm_ret = isl29028_set_pm_runtime_busy(chip, false);
+	if (pm_ret < 0)
+		return pm_ret;
+
+	return ret;
+}
+
+static IIO_CONST_ATTR(in_proximity_sampling_frequency_available,
+				"1.25 2.5 5 10 13.3 20 80 100");
+static IIO_CONST_ATTR(in_illuminance_scale_available, "125 2000");
+
+#define ISL29028_CONST_ATTR(name) (&iio_const_attr_##name.dev_attr.attr)
+static struct attribute *isl29028_attributes[] = {
+	ISL29028_CONST_ATTR(in_proximity_sampling_frequency_available),
+	ISL29028_CONST_ATTR(in_illuminance_scale_available),
+	NULL,
+};
+
+static const struct attribute_group isl29108_group = {
+	.attrs = isl29028_attributes,
+};
+
+static const struct iio_chan_spec isl29028_channels[] = {
+	{
+		.type = IIO_LIGHT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
+		BIT(IIO_CHAN_INFO_SCALE),
+	}, {
+		.type = IIO_INTENSITY,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+	}, {
+		.type = IIO_PROXIMITY,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+		BIT(IIO_CHAN_INFO_SAMP_FREQ),
+	}
+};
+
+static const struct iio_info isl29028_info = {
+	.attrs = &isl29108_group,
+	.driver_module = THIS_MODULE,
+	.read_raw = isl29028_read_raw,
+	.write_raw = isl29028_write_raw,
+};
+
+static int isl29028_clear_configure_reg(struct isl29028_chip *chip)
+{
+	struct device *dev = regmap_get_device(chip->regmap);
+	int ret;
+
+	ret = regmap_write(chip->regmap, ISL29028_REG_CONFIGURE, 0x0);
+	if (ret < 0)
+		dev_err(dev, "%s(): Error %d clearing the CONFIGURE register\n",
+			__func__, ret);
+
+	chip->als_ir_mode = ISL29028_MODE_NONE;
+	chip->enable_prox = false;
+
+	return ret;
+}
+
+static bool isl29028_is_volatile_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case ISL29028_REG_INTERRUPT:
+	case ISL29028_REG_PROX_DATA:
+	case ISL29028_REG_ALSIR_L:
+	case ISL29028_REG_ALSIR_U:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static const struct regmap_config isl29028_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.volatile_reg = isl29028_is_volatile_reg,
+	.max_register = ISL29028_NUM_REGS - 1,
+	.num_reg_defaults_raw = ISL29028_NUM_REGS,
+	.cache_type = REGCACHE_RBTREE,
+};
+
+static int isl29028_probe(struct i2c_client *client,
+			  const struct i2c_device_id *id)
+{
+	struct isl29028_chip *chip;
+	struct iio_dev *indio_dev;
+	int ret;
+
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	chip = iio_priv(indio_dev);
+
+	i2c_set_clientdata(client, indio_dev);
+	mutex_init(&chip->lock);
+
+	chip->regmap = devm_regmap_init_i2c(client, &isl29028_regmap_config);
+	if (IS_ERR(chip->regmap)) {
+		ret = PTR_ERR(chip->regmap);
+		dev_err(&client->dev, "%s: Error %d initializing regmap\n",
+			__func__, ret);
+		return ret;
+	}
+
+	chip->enable_prox  = false;
+	chip->prox_sampling_int = 20;
+	chip->prox_sampling_frac = 0;
+	chip->lux_scale = 2000;
+
+	ret = regmap_write(chip->regmap, ISL29028_REG_TEST1_MODE, 0x0);
+	if (ret < 0) {
+		dev_err(&client->dev,
+			"%s(): Error %d writing to TEST1_MODE register\n",
+			__func__, ret);
+		return ret;
+	}
+
+	ret = regmap_write(chip->regmap, ISL29028_REG_TEST2_MODE, 0x0);
+	if (ret < 0) {
+		dev_err(&client->dev,
+			"%s(): Error %d writing to TEST2_MODE register\n",
+			__func__, ret);
+		return ret;
+	}
+
+	ret = isl29028_clear_configure_reg(chip);
+	if (ret < 0)
+		return ret;
+
+	indio_dev->info = &isl29028_info;
+	indio_dev->channels = isl29028_channels;
+	indio_dev->num_channels = ARRAY_SIZE(isl29028_channels);
+	indio_dev->name = id->name;
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+
+	pm_runtime_enable(&client->dev);
+	pm_runtime_set_autosuspend_delay(&client->dev,
+					 ISL29028_POWER_OFF_DELAY_MS);
+	pm_runtime_use_autosuspend(&client->dev);
+
+	ret = devm_iio_device_register(indio_dev->dev.parent, indio_dev);
+	if (ret < 0) {
+		dev_err(&client->dev,
+			"%s(): iio registration failed with error %d\n",
+			__func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int isl29028_remove(struct i2c_client *client)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+	struct isl29028_chip *chip = iio_priv(indio_dev);
+
+	iio_device_unregister(indio_dev);
+
+	pm_runtime_disable(&client->dev);
+	pm_runtime_set_suspended(&client->dev);
+	pm_runtime_put_noidle(&client->dev);
+
+	return isl29028_clear_configure_reg(chip);
+}
+
+static int __maybe_unused isl29028_suspend(struct device *dev)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
+	struct isl29028_chip *chip = iio_priv(indio_dev);
+	int ret;
+
+	mutex_lock(&chip->lock);
+
+	ret = isl29028_clear_configure_reg(chip);
+
+	mutex_unlock(&chip->lock);
+
+	return ret;
+}
+
+static int __maybe_unused isl29028_resume(struct device *dev)
+{
+	/**
+	 * The specific component (ALS/IR or proximity) will enable itself as
+	 * needed the next time that the user requests a reading. This is done
+	 * above in isl29028_set_als_ir_mode() and isl29028_enable_proximity().
+	 */
+	return 0;
+}
+
+static const struct dev_pm_ops isl29028_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+				pm_runtime_force_resume)
+	SET_RUNTIME_PM_OPS(isl29028_suspend, isl29028_resume, NULL)
+};
+
+static const struct i2c_device_id isl29028_id[] = {
+	{"isl29028", 0},
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, isl29028_id);
+
+static const struct of_device_id isl29028_of_match[] = {
+	{ .compatible = "isl,isl29028", }, /* for backward compat., don't use */
+	{ .compatible = "isil,isl29028", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, isl29028_of_match);
+
+static struct i2c_driver isl29028_driver = {
+	.driver  = {
+		.name = "isl29028",
+		.pm = &isl29028_pm_ops,
+		.of_match_table = isl29028_of_match,
+	},
+	.probe	 = isl29028_probe,
+	.remove  = isl29028_remove,
+	.id_table = isl29028_id,
+};
+
+module_i2c_driver(isl29028_driver);
+
+MODULE_DESCRIPTION("ISL29028 Ambient Light and Proximity Sensor driver");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
diff --git a/drivers/staging/iio/light/Kconfig b/drivers/staging/iio/light/Kconfig
index 4fbf629..aacb0ae 100644
--- a/drivers/staging/iio/light/Kconfig
+++ b/drivers/staging/iio/light/Kconfig
@@ -3,16 +3,6 @@
 #
 menu "Light sensors"
 
-config SENSORS_ISL29028
-	tristate "Intersil ISL29028 Concurrent Light and Proximity Sensor"
-	depends on I2C
-	select REGMAP_I2C
-	help
-	 Provides driver for the Intersil's ISL29028 device.
-	 This driver supports the sysfs interface to get the ALS, IR intensity,
-	 Proximity value via iio. The ISL29028 provides the concurrent sensing
-	 of ambient light and proximity.
-
 config TSL2x7x
 	tristate "TAOS TSL/TMD2x71 and TSL/TMD2x72 Family of light and proximity sensors"
 	depends on I2C
diff --git a/drivers/staging/iio/light/Makefile b/drivers/staging/iio/light/Makefile
index f8693e9..10286c3 100644
--- a/drivers/staging/iio/light/Makefile
+++ b/drivers/staging/iio/light/Makefile
@@ -2,5 +2,4 @@
 # Makefile for industrial I/O Light sensors
 #
 
-obj-$(CONFIG_SENSORS_ISL29028)	+= isl29028.o
 obj-$(CONFIG_TSL2x7x)	+= tsl2x7x_core.o
diff --git a/drivers/staging/iio/light/isl29028.c b/drivers/staging/iio/light/isl29028.c
deleted file mode 100644
index aeb5082..0000000
--- a/drivers/staging/iio/light/isl29028.c
+++ /dev/null
@@ -1,723 +0,0 @@
-/*
- * IIO driver for the light sensor ISL29028.
- * ISL29028 is Concurrent Ambient Light and Proximity Sensor
- *
- * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
- * Copyright (c) 2016-2017 Brian Masney <masneyb@onstation.org>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * 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, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/module.h>
-#include <linux/i2c.h>
-#include <linux/err.h>
-#include <linux/mutex.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/regmap.h>
-#include <linux/iio/iio.h>
-#include <linux/iio/sysfs.h>
-#include <linux/pm_runtime.h>
-
-#define ISL29028_CONV_TIME_MS			100
-
-#define ISL29028_REG_CONFIGURE			0x01
-
-#define ISL29028_CONF_ALS_IR_MODE_ALS		0
-#define ISL29028_CONF_ALS_IR_MODE_IR		BIT(0)
-#define ISL29028_CONF_ALS_IR_MODE_MASK		BIT(0)
-
-#define ISL29028_CONF_ALS_RANGE_LOW_LUX		0
-#define ISL29028_CONF_ALS_RANGE_HIGH_LUX	BIT(1)
-#define ISL29028_CONF_ALS_RANGE_MASK		BIT(1)
-
-#define ISL29028_CONF_ALS_DIS			0
-#define ISL29028_CONF_ALS_EN			BIT(2)
-#define ISL29028_CONF_ALS_EN_MASK		BIT(2)
-
-#define ISL29028_CONF_PROX_SLP_SH		4
-#define ISL29028_CONF_PROX_SLP_MASK		(7 << ISL29028_CONF_PROX_SLP_SH)
-
-#define ISL29028_CONF_PROX_EN			BIT(7)
-#define ISL29028_CONF_PROX_EN_MASK		BIT(7)
-
-#define ISL29028_REG_INTERRUPT			0x02
-
-#define ISL29028_REG_PROX_DATA			0x08
-#define ISL29028_REG_ALSIR_L			0x09
-#define ISL29028_REG_ALSIR_U			0x0A
-
-#define ISL29028_REG_TEST1_MODE			0x0E
-#define ISL29028_REG_TEST2_MODE			0x0F
-
-#define ISL29028_NUM_REGS			(ISL29028_REG_TEST2_MODE + 1)
-
-#define ISL29028_POWER_OFF_DELAY_MS		2000
-
-struct isl29028_prox_data {
-	int sampling_int;
-	int sampling_fract;
-	int sleep_time;
-};
-
-static const struct isl29028_prox_data isl29028_prox_data[] = {
-	{   1, 250000, 800 },
-	{   2, 500000, 400 },
-	{   5,      0, 200 },
-	{  10,      0, 100 },
-	{  13, 300000,  75 },
-	{  20,      0,  50 },
-	{  80,      0,  13 }, /*
-			       * Note: Data sheet lists 12.5 ms sleep time.
-			       * Round up a half millisecond for msleep().
-			       */
-	{ 100,  0,   0 }
-};
-
-enum isl29028_als_ir_mode {
-	ISL29028_MODE_NONE = 0,
-	ISL29028_MODE_ALS,
-	ISL29028_MODE_IR,
-};
-
-struct isl29028_chip {
-	struct mutex			lock;
-	struct regmap			*regmap;
-	int				prox_sampling_int;
-	int				prox_sampling_frac;
-	bool				enable_prox;
-	int				lux_scale;
-	enum isl29028_als_ir_mode	als_ir_mode;
-};
-
-static int isl29028_find_prox_sleep_index(int sampling_int, int sampling_fract)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(isl29028_prox_data); ++i) {
-		if (isl29028_prox_data[i].sampling_int == sampling_int &&
-		    isl29028_prox_data[i].sampling_fract == sampling_fract)
-			return i;
-	}
-
-	return -EINVAL;
-}
-
-static int isl29028_set_proxim_sampling(struct isl29028_chip *chip,
-					int sampling_int, int sampling_fract)
-{
-	struct device *dev = regmap_get_device(chip->regmap);
-	int sleep_index, ret;
-
-	sleep_index = isl29028_find_prox_sleep_index(sampling_int,
-						     sampling_fract);
-	if (sleep_index < 0)
-		return sleep_index;
-
-	ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
-				 ISL29028_CONF_PROX_SLP_MASK,
-				 sleep_index << ISL29028_CONF_PROX_SLP_SH);
-
-	if (ret < 0) {
-		dev_err(dev, "%s(): Error %d setting the proximity sampling\n",
-			__func__, ret);
-		return ret;
-	}
-
-	chip->prox_sampling_int = sampling_int;
-	chip->prox_sampling_frac = sampling_fract;
-
-	return ret;
-}
-
-static int isl29028_enable_proximity(struct isl29028_chip *chip)
-{
-	int prox_index, ret;
-
-	ret = isl29028_set_proxim_sampling(chip, chip->prox_sampling_int,
-					   chip->prox_sampling_frac);
-	if (ret < 0)
-		return ret;
-
-	ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
-				 ISL29028_CONF_PROX_EN_MASK,
-				 ISL29028_CONF_PROX_EN);
-	if (ret < 0)
-		return ret;
-
-	/* Wait for conversion to be complete for first sample */
-	prox_index = isl29028_find_prox_sleep_index(chip->prox_sampling_int,
-						    chip->prox_sampling_frac);
-	if (prox_index < 0)
-		return prox_index;
-
-	msleep(isl29028_prox_data[prox_index].sleep_time);
-
-	return 0;
-}
-
-static int isl29028_set_als_scale(struct isl29028_chip *chip, int lux_scale)
-{
-	struct device *dev = regmap_get_device(chip->regmap);
-	int val = (lux_scale == 2000) ? ISL29028_CONF_ALS_RANGE_HIGH_LUX :
-					ISL29028_CONF_ALS_RANGE_LOW_LUX;
-	int ret;
-
-	ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
-				 ISL29028_CONF_ALS_RANGE_MASK, val);
-	if (ret < 0) {
-		dev_err(dev, "%s(): Error %d setting the ALS scale\n", __func__,
-			ret);
-		return ret;
-	}
-
-	chip->lux_scale = lux_scale;
-
-	return ret;
-}
-
-static int isl29028_set_als_ir_mode(struct isl29028_chip *chip,
-				    enum isl29028_als_ir_mode mode)
-{
-	int ret;
-
-	if (chip->als_ir_mode == mode)
-		return 0;
-
-	ret = isl29028_set_als_scale(chip, chip->lux_scale);
-	if (ret < 0)
-		return ret;
-
-	switch (mode) {
-	case ISL29028_MODE_ALS:
-		ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
-					 ISL29028_CONF_ALS_IR_MODE_MASK,
-					 ISL29028_CONF_ALS_IR_MODE_ALS);
-		if (ret < 0)
-			return ret;
-
-		ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
-					 ISL29028_CONF_ALS_RANGE_MASK,
-					 ISL29028_CONF_ALS_RANGE_HIGH_LUX);
-		break;
-	case ISL29028_MODE_IR:
-		ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
-					 ISL29028_CONF_ALS_IR_MODE_MASK,
-					 ISL29028_CONF_ALS_IR_MODE_IR);
-		break;
-	case ISL29028_MODE_NONE:
-		return regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
-					  ISL29028_CONF_ALS_EN_MASK,
-					  ISL29028_CONF_ALS_DIS);
-	}
-
-	if (ret < 0)
-		return ret;
-
-	/* Enable the ALS/IR */
-	ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
-				 ISL29028_CONF_ALS_EN_MASK,
-				 ISL29028_CONF_ALS_EN);
-	if (ret < 0)
-		return ret;
-
-	/* Need to wait for conversion time if ALS/IR mode enabled */
-	msleep(ISL29028_CONV_TIME_MS);
-
-	chip->als_ir_mode = mode;
-
-	return 0;
-}
-
-static int isl29028_read_als_ir(struct isl29028_chip *chip, int *als_ir)
-{
-	struct device *dev = regmap_get_device(chip->regmap);
-	unsigned int lsb;
-	unsigned int msb;
-	int ret;
-
-	ret = regmap_read(chip->regmap, ISL29028_REG_ALSIR_L, &lsb);
-	if (ret < 0) {
-		dev_err(dev,
-			"%s(): Error %d reading register ALSIR_L\n",
-			__func__, ret);
-		return ret;
-	}
-
-	ret = regmap_read(chip->regmap, ISL29028_REG_ALSIR_U, &msb);
-	if (ret < 0) {
-		dev_err(dev,
-			"%s(): Error %d reading register ALSIR_U\n",
-			__func__, ret);
-		return ret;
-	}
-
-	*als_ir = ((msb & 0xF) << 8) | (lsb & 0xFF);
-
-	return 0;
-}
-
-static int isl29028_read_proxim(struct isl29028_chip *chip, int *prox)
-{
-	struct device *dev = regmap_get_device(chip->regmap);
-	unsigned int data;
-	int ret;
-
-	if (!chip->enable_prox) {
-		ret = isl29028_enable_proximity(chip);
-		if (ret < 0)
-			return ret;
-
-		chip->enable_prox = true;
-	}
-
-	ret = regmap_read(chip->regmap, ISL29028_REG_PROX_DATA, &data);
-	if (ret < 0) {
-		dev_err(dev, "%s(): Error %d reading register PROX_DATA\n",
-			__func__, ret);
-		return ret;
-	}
-
-	*prox = data;
-
-	return 0;
-}
-
-static int isl29028_als_get(struct isl29028_chip *chip, int *als_data)
-{
-	struct device *dev = regmap_get_device(chip->regmap);
-	int ret;
-	int als_ir_data;
-
-	ret = isl29028_set_als_ir_mode(chip, ISL29028_MODE_ALS);
-	if (ret < 0) {
-		dev_err(dev, "%s(): Error %d enabling ALS mode\n", __func__,
-			ret);
-		return ret;
-	}
-
-	ret = isl29028_read_als_ir(chip, &als_ir_data);
-	if (ret < 0)
-		return ret;
-
-	/*
-	 * convert als data count to lux.
-	 * if lux_scale = 125,  lux = count * 0.031
-	 * if lux_scale = 2000, lux = count * 0.49
-	 */
-	if (chip->lux_scale == 125)
-		als_ir_data = (als_ir_data * 31) / 1000;
-	else
-		als_ir_data = (als_ir_data * 49) / 100;
-
-	*als_data = als_ir_data;
-
-	return 0;
-}
-
-static int isl29028_ir_get(struct isl29028_chip *chip, int *ir_data)
-{
-	struct device *dev = regmap_get_device(chip->regmap);
-	int ret;
-
-	ret = isl29028_set_als_ir_mode(chip, ISL29028_MODE_IR);
-	if (ret < 0) {
-		dev_err(dev, "%s(): Error %d enabling IR mode\n", __func__,
-			ret);
-		return ret;
-	}
-
-	return isl29028_read_als_ir(chip, ir_data);
-}
-
-static int isl29028_set_pm_runtime_busy(struct isl29028_chip *chip, bool on)
-{
-	struct device *dev = regmap_get_device(chip->regmap);
-	int ret;
-
-	if (on) {
-		ret = pm_runtime_get_sync(dev);
-		if (ret < 0)
-			pm_runtime_put_noidle(dev);
-	} else {
-		pm_runtime_mark_last_busy(dev);
-		ret = pm_runtime_put_autosuspend(dev);
-	}
-
-	return ret;
-}
-
-/* Channel IO */
-static int isl29028_write_raw(struct iio_dev *indio_dev,
-			      struct iio_chan_spec const *chan,
-			      int val, int val2, long mask)
-{
-	struct isl29028_chip *chip = iio_priv(indio_dev);
-	struct device *dev = regmap_get_device(chip->regmap);
-	int ret;
-
-	ret = isl29028_set_pm_runtime_busy(chip, true);
-	if (ret < 0)
-		return ret;
-
-	mutex_lock(&chip->lock);
-
-	ret = -EINVAL;
-	switch (chan->type) {
-	case IIO_PROXIMITY:
-		if (mask != IIO_CHAN_INFO_SAMP_FREQ) {
-			dev_err(dev,
-				"%s(): proximity: Mask value 0x%08lx is not supported\n",
-				__func__, mask);
-			break;
-		}
-
-		if (val < 1 || val > 100) {
-			dev_err(dev,
-				"%s(): proximity: Sampling frequency %d is not in the range [1:100]\n",
-				__func__, val);
-			break;
-		}
-
-		ret = isl29028_set_proxim_sampling(chip, val, val2);
-		break;
-	case IIO_LIGHT:
-		if (mask != IIO_CHAN_INFO_SCALE) {
-			dev_err(dev,
-				"%s(): light: Mask value 0x%08lx is not supported\n",
-				__func__, mask);
-			break;
-		}
-
-		if (val != 125 && val != 2000) {
-			dev_err(dev,
-				"%s(): light: Lux scale %d is not in the set {125, 2000}\n",
-				__func__, val);
-			break;
-		}
-
-		ret = isl29028_set_als_scale(chip, val);
-		break;
-	default:
-		dev_err(dev, "%s(): Unsupported channel type %x\n",
-			__func__, chan->type);
-		break;
-	}
-
-	mutex_unlock(&chip->lock);
-
-	if (ret < 0)
-		return ret;
-
-	ret = isl29028_set_pm_runtime_busy(chip, false);
-	if (ret < 0)
-		return ret;
-
-	return ret;
-}
-
-static int isl29028_read_raw(struct iio_dev *indio_dev,
-			     struct iio_chan_spec const *chan,
-			     int *val, int *val2, long mask)
-{
-	struct isl29028_chip *chip = iio_priv(indio_dev);
-	struct device *dev = regmap_get_device(chip->regmap);
-	int ret, pm_ret;
-
-	ret = isl29028_set_pm_runtime_busy(chip, true);
-	if (ret < 0)
-		return ret;
-
-	mutex_lock(&chip->lock);
-
-	ret = -EINVAL;
-	switch (mask) {
-	case IIO_CHAN_INFO_RAW:
-	case IIO_CHAN_INFO_PROCESSED:
-		switch (chan->type) {
-		case IIO_LIGHT:
-			ret = isl29028_als_get(chip, val);
-			break;
-		case IIO_INTENSITY:
-			ret = isl29028_ir_get(chip, val);
-			break;
-		case IIO_PROXIMITY:
-			ret = isl29028_read_proxim(chip, val);
-			break;
-		default:
-			break;
-		}
-
-		if (ret < 0)
-			break;
-
-		ret = IIO_VAL_INT;
-		break;
-	case IIO_CHAN_INFO_SAMP_FREQ:
-		if (chan->type != IIO_PROXIMITY)
-			break;
-
-		*val = chip->prox_sampling_int;
-		*val2 = chip->prox_sampling_frac;
-		ret = IIO_VAL_INT;
-		break;
-	case IIO_CHAN_INFO_SCALE:
-		if (chan->type != IIO_LIGHT)
-			break;
-		*val = chip->lux_scale;
-		ret = IIO_VAL_INT;
-		break;
-	default:
-		dev_err(dev, "%s(): mask value 0x%08lx is not supported\n",
-			__func__, mask);
-		break;
-	}
-
-	mutex_unlock(&chip->lock);
-
-	if (ret < 0)
-		return ret;
-
-	/**
-	 * Preserve the ret variable if the call to
-	 * isl29028_set_pm_runtime_busy() is successful so the reading
-	 * (if applicable) is returned to user space.
-	 */
-	pm_ret = isl29028_set_pm_runtime_busy(chip, false);
-	if (pm_ret < 0)
-		return pm_ret;
-
-	return ret;
-}
-
-static IIO_CONST_ATTR(in_proximity_sampling_frequency_available,
-				"1.25 2.5 5 10 13.3 20 80 100");
-static IIO_CONST_ATTR(in_illuminance_scale_available, "125 2000");
-
-#define ISL29028_CONST_ATTR(name) (&iio_const_attr_##name.dev_attr.attr)
-static struct attribute *isl29028_attributes[] = {
-	ISL29028_CONST_ATTR(in_proximity_sampling_frequency_available),
-	ISL29028_CONST_ATTR(in_illuminance_scale_available),
-	NULL,
-};
-
-static const struct attribute_group isl29108_group = {
-	.attrs = isl29028_attributes,
-};
-
-static const struct iio_chan_spec isl29028_channels[] = {
-	{
-		.type = IIO_LIGHT,
-		.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
-		BIT(IIO_CHAN_INFO_SCALE),
-	}, {
-		.type = IIO_INTENSITY,
-		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
-	}, {
-		.type = IIO_PROXIMITY,
-		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
-		BIT(IIO_CHAN_INFO_SAMP_FREQ),
-	}
-};
-
-static const struct iio_info isl29028_info = {
-	.attrs = &isl29108_group,
-	.driver_module = THIS_MODULE,
-	.read_raw = isl29028_read_raw,
-	.write_raw = isl29028_write_raw,
-};
-
-static int isl29028_clear_configure_reg(struct isl29028_chip *chip)
-{
-	struct device *dev = regmap_get_device(chip->regmap);
-	int ret;
-
-	ret = regmap_write(chip->regmap, ISL29028_REG_CONFIGURE, 0x0);
-	if (ret < 0)
-		dev_err(dev, "%s(): Error %d clearing the CONFIGURE register\n",
-			__func__, ret);
-
-	chip->als_ir_mode = ISL29028_MODE_NONE;
-	chip->enable_prox = false;
-
-	return ret;
-}
-
-static bool isl29028_is_volatile_reg(struct device *dev, unsigned int reg)
-{
-	switch (reg) {
-	case ISL29028_REG_INTERRUPT:
-	case ISL29028_REG_PROX_DATA:
-	case ISL29028_REG_ALSIR_L:
-	case ISL29028_REG_ALSIR_U:
-		return true;
-	default:
-		return false;
-	}
-}
-
-static const struct regmap_config isl29028_regmap_config = {
-	.reg_bits = 8,
-	.val_bits = 8,
-	.volatile_reg = isl29028_is_volatile_reg,
-	.max_register = ISL29028_NUM_REGS - 1,
-	.num_reg_defaults_raw = ISL29028_NUM_REGS,
-	.cache_type = REGCACHE_RBTREE,
-};
-
-static int isl29028_probe(struct i2c_client *client,
-			  const struct i2c_device_id *id)
-{
-	struct isl29028_chip *chip;
-	struct iio_dev *indio_dev;
-	int ret;
-
-	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip));
-	if (!indio_dev)
-		return -ENOMEM;
-
-	chip = iio_priv(indio_dev);
-
-	i2c_set_clientdata(client, indio_dev);
-	mutex_init(&chip->lock);
-
-	chip->regmap = devm_regmap_init_i2c(client, &isl29028_regmap_config);
-	if (IS_ERR(chip->regmap)) {
-		ret = PTR_ERR(chip->regmap);
-		dev_err(&client->dev, "%s: Error %d initializing regmap\n",
-			__func__, ret);
-		return ret;
-	}
-
-	chip->enable_prox  = false;
-	chip->prox_sampling_int = 20;
-	chip->prox_sampling_frac = 0;
-	chip->lux_scale = 2000;
-
-	ret = regmap_write(chip->regmap, ISL29028_REG_TEST1_MODE, 0x0);
-	if (ret < 0) {
-		dev_err(&client->dev,
-			"%s(): Error %d writing to TEST1_MODE register\n",
-			__func__, ret);
-		return ret;
-	}
-
-	ret = regmap_write(chip->regmap, ISL29028_REG_TEST2_MODE, 0x0);
-	if (ret < 0) {
-		dev_err(&client->dev,
-			"%s(): Error %d writing to TEST2_MODE register\n",
-			__func__, ret);
-		return ret;
-	}
-
-	ret = isl29028_clear_configure_reg(chip);
-	if (ret < 0)
-		return ret;
-
-	indio_dev->info = &isl29028_info;
-	indio_dev->channels = isl29028_channels;
-	indio_dev->num_channels = ARRAY_SIZE(isl29028_channels);
-	indio_dev->name = id->name;
-	indio_dev->dev.parent = &client->dev;
-	indio_dev->modes = INDIO_DIRECT_MODE;
-
-	pm_runtime_enable(&client->dev);
-	pm_runtime_set_autosuspend_delay(&client->dev,
-					 ISL29028_POWER_OFF_DELAY_MS);
-	pm_runtime_use_autosuspend(&client->dev);
-
-	ret = devm_iio_device_register(indio_dev->dev.parent, indio_dev);
-	if (ret < 0) {
-		dev_err(&client->dev,
-			"%s(): iio registration failed with error %d\n",
-			__func__, ret);
-		return ret;
-	}
-
-	return 0;
-}
-
-static int isl29028_remove(struct i2c_client *client)
-{
-	struct iio_dev *indio_dev = i2c_get_clientdata(client);
-	struct isl29028_chip *chip = iio_priv(indio_dev);
-
-	iio_device_unregister(indio_dev);
-
-	pm_runtime_disable(&client->dev);
-	pm_runtime_set_suspended(&client->dev);
-	pm_runtime_put_noidle(&client->dev);
-
-	return isl29028_clear_configure_reg(chip);
-}
-
-static int __maybe_unused isl29028_suspend(struct device *dev)
-{
-	struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
-	struct isl29028_chip *chip = iio_priv(indio_dev);
-	int ret;
-
-	mutex_lock(&chip->lock);
-
-	ret = isl29028_clear_configure_reg(chip);
-
-	mutex_unlock(&chip->lock);
-
-	return ret;
-}
-
-static int __maybe_unused isl29028_resume(struct device *dev)
-{
-	/**
-	 * The specific component (ALS/IR or proximity) will enable itself as
-	 * needed the next time that the user requests a reading. This is done
-	 * above in isl29028_set_als_ir_mode() and isl29028_enable_proximity().
-	 */
-	return 0;
-}
-
-static const struct dev_pm_ops isl29028_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
-				pm_runtime_force_resume)
-	SET_RUNTIME_PM_OPS(isl29028_suspend, isl29028_resume, NULL)
-};
-
-static const struct i2c_device_id isl29028_id[] = {
-	{"isl29028", 0},
-	{}
-};
-MODULE_DEVICE_TABLE(i2c, isl29028_id);
-
-static const struct of_device_id isl29028_of_match[] = {
-	{ .compatible = "isl,isl29028", }, /* for backward compat., don't use */
-	{ .compatible = "isil,isl29028", },
-	{ },
-};
-MODULE_DEVICE_TABLE(of, isl29028_of_match);
-
-static struct i2c_driver isl29028_driver = {
-	.driver  = {
-		.name = "isl29028",
-		.pm = &isl29028_pm_ops,
-		.of_match_table = isl29028_of_match,
-	},
-	.probe	 = isl29028_probe,
-	.remove  = isl29028_remove,
-	.id_table = isl29028_id,
-};
-
-module_i2c_driver(isl29028_driver);
-
-MODULE_DESCRIPTION("ISL29028 Ambient Light and Proximity Sensor driver");
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH v3 0/2] staging: iio: isl29028: move out of staging
  2017-04-25  1:34 [PATCH v3 0/2] staging: iio: isl29028: move out of staging Brian Masney
  2017-04-25  1:34 ` [PATCH v3 1/2] staging: iio: isl29028: correct proximity sleep times Brian Masney
  2017-04-25  1:34 ` [PATCH v3 2/2] staging: iio: isl29028: move out of staging Brian Masney
@ 2017-04-26  5:25 ` Jonathan Cameron
  2 siblings, 0 replies; 8+ messages in thread
From: Jonathan Cameron @ 2017-04-26  5:25 UTC (permalink / raw)
  To: Brian Masney, linux-iio
  Cc: gregkh, devel, knaack.h, lars, pmeerw, linux-kernel, ldewangan

On 25/04/17 02:34, Brian Masney wrote:
> Minor cleanup to the proximity sampling to move this driver out of
> staging.
> 
> Datasheet:
> http://www.intersil.com/content/dam/Intersil/documents/isl2/isl29028.pdf
> 
> Changes since v2:
> - Reject any value that is not in the
>   in_proximity_sampling_frequency_available sysfs attribute.
> - Changed the sampling frequency 83.3 to 80. The data sheet lists 12.5
>   ms, but the original code listed 12 ms, which was the cause of the
>   discrepancy.
> Changes since v1:
> - in_proximity_sampling_frequency_available sysfs attribute now shows
>   decimals.
> 
> Jonathan: Sorry it took me a little over two months to get back to you
> on this driver. I got side tracked with other projects.
*laughs* I have series that I haven't gotten back to reviews on in
years!  What's a few months ;)

Thanks though as this work is good stuff!

Jonathan
> 
> Brian Masney (2):
>   staging: iio: isl29028: correct proximity sleep times
>   staging: iio: isl29028: move out of staging
> 
>  drivers/iio/light/Kconfig            |  10 +
>  drivers/iio/light/Makefile           |   1 +
>  drivers/iio/light/isl29028.c         | 723 +++++++++++++++++++++++++++++++++++
>  drivers/staging/iio/light/Kconfig    |  10 -
>  drivers/staging/iio/light/Makefile   |   1 -
>  drivers/staging/iio/light/isl29028.c | 693 ---------------------------------
>  6 files changed, 734 insertions(+), 704 deletions(-)
>  create mode 100644 drivers/iio/light/isl29028.c
>  delete mode 100644 drivers/staging/iio/light/isl29028.c
> 

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v3 1/2] staging: iio: isl29028: correct proximity sleep times
  2017-04-25  1:34 ` [PATCH v3 1/2] staging: iio: isl29028: correct proximity sleep times Brian Masney
@ 2017-04-26  5:30   ` Jonathan Cameron
  0 siblings, 0 replies; 8+ messages in thread
From: Jonathan Cameron @ 2017-04-26  5:30 UTC (permalink / raw)
  To: Brian Masney, linux-iio
  Cc: gregkh, devel, knaack.h, lars, pmeerw, linux-kernel, ldewangan

On 25/04/17 02:34, Brian Masney wrote:
> The sysfs attribute in_proximity_sampling_frequency_available currently
> shows the values 1 3 5 10 13 20 83 100. These values are supposed to
> correspond to the sleep values 800 400 200 100 75 50 12.5 0 (all in ms).
> When passing in a sampling frequency of 3, it actually uses a sleep
> time of 200ms instead of the expected 400ms value. This patch changes
> the value shown by this sysfs attribute to use fixed-point numbers so
> that the correct sampling frequency is shown to the user. This patch
> also changes the code that updates the proximity sampling frequency to
> only allow values that are shown in the _available sysfs attribute.
> 
> The original code showed the value 83 that corresponds to the sleep
> time 12 ms. The data sheet actually lists 12.5 ms as the sleep time,
> so the proximity frequency was updated to 80.
> 
> Signed-off-by: Brian Masney <masneyb@onstation.org>
Applied to the togreg branch of iio.git and pushed out as testing for the
autobuilders to play with it.

Thanks,

Jonathan
> ---
>  drivers/staging/iio/light/isl29028.c | 70 +++++++++++++++++++++++++-----------
>  1 file changed, 50 insertions(+), 20 deletions(-)
> 
> diff --git a/drivers/staging/iio/light/isl29028.c b/drivers/staging/iio/light/isl29028.c
> index 5375e7a..aeb5082 100644
> --- a/drivers/staging/iio/light/isl29028.c
> +++ b/drivers/staging/iio/light/isl29028.c
> @@ -64,8 +64,25 @@
>  
>  #define ISL29028_POWER_OFF_DELAY_MS		2000
>  
> -static const unsigned int isl29028_prox_sleep_time[] = {800, 400, 200, 100, 75,
> -							50, 12, 0};
> +struct isl29028_prox_data {
> +	int sampling_int;
> +	int sampling_fract;
> +	int sleep_time;
> +};
> +
> +static const struct isl29028_prox_data isl29028_prox_data[] = {
> +	{   1, 250000, 800 },
> +	{   2, 500000, 400 },
> +	{   5,      0, 200 },
> +	{  10,      0, 100 },
> +	{  13, 300000,  75 },
> +	{  20,      0,  50 },
> +	{  80,      0,  13 }, /*
> +			       * Note: Data sheet lists 12.5 ms sleep time.
> +			       * Round up a half millisecond for msleep().
> +			       */
> +	{ 100,  0,   0 }
> +};
>  
>  enum isl29028_als_ir_mode {
>  	ISL29028_MODE_NONE = 0,
> @@ -76,32 +93,37 @@ enum isl29028_als_ir_mode {
>  struct isl29028_chip {
>  	struct mutex			lock;
>  	struct regmap			*regmap;
> -	unsigned int			prox_sampling;
> +	int				prox_sampling_int;
> +	int				prox_sampling_frac;
>  	bool				enable_prox;
>  	int				lux_scale;
>  	enum isl29028_als_ir_mode	als_ir_mode;
>  };
>  
> -static int isl29028_find_prox_sleep_time_index(int sampling)
> +static int isl29028_find_prox_sleep_index(int sampling_int, int sampling_fract)
>  {
> -	unsigned int period = DIV_ROUND_UP(1000, sampling);
>  	int i;
>  
> -	for (i = 0; i < ARRAY_SIZE(isl29028_prox_sleep_time); ++i) {
> -		if (period >= isl29028_prox_sleep_time[i])
> -			break;
> +	for (i = 0; i < ARRAY_SIZE(isl29028_prox_data); ++i) {
> +		if (isl29028_prox_data[i].sampling_int == sampling_int &&
> +		    isl29028_prox_data[i].sampling_fract == sampling_fract)
> +			return i;
>  	}
>  
> -	return i;
> +	return -EINVAL;
>  }
>  
>  static int isl29028_set_proxim_sampling(struct isl29028_chip *chip,
> -					unsigned int sampling)
> +					int sampling_int, int sampling_fract)
>  {
>  	struct device *dev = regmap_get_device(chip->regmap);
>  	int sleep_index, ret;
>  
> -	sleep_index = isl29028_find_prox_sleep_time_index(sampling);
> +	sleep_index = isl29028_find_prox_sleep_index(sampling_int,
> +						     sampling_fract);
> +	if (sleep_index < 0)
> +		return sleep_index;
> +
>  	ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
>  				 ISL29028_CONF_PROX_SLP_MASK,
>  				 sleep_index << ISL29028_CONF_PROX_SLP_SH);
> @@ -112,16 +134,18 @@ static int isl29028_set_proxim_sampling(struct isl29028_chip *chip,
>  		return ret;
>  	}
>  
> -	chip->prox_sampling = sampling;
> +	chip->prox_sampling_int = sampling_int;
> +	chip->prox_sampling_frac = sampling_fract;
>  
>  	return ret;
>  }
>  
>  static int isl29028_enable_proximity(struct isl29028_chip *chip)
>  {
> -	int sleep_index, ret;
> +	int prox_index, ret;
>  
> -	ret = isl29028_set_proxim_sampling(chip, chip->prox_sampling);
> +	ret = isl29028_set_proxim_sampling(chip, chip->prox_sampling_int,
> +					   chip->prox_sampling_frac);
>  	if (ret < 0)
>  		return ret;
>  
> @@ -132,8 +156,12 @@ static int isl29028_enable_proximity(struct isl29028_chip *chip)
>  		return ret;
>  
>  	/* Wait for conversion to be complete for first sample */
> -	sleep_index = isl29028_find_prox_sleep_time_index(chip->prox_sampling);
> -	msleep(isl29028_prox_sleep_time[sleep_index]);
> +	prox_index = isl29028_find_prox_sleep_index(chip->prox_sampling_int,
> +						    chip->prox_sampling_frac);
> +	if (prox_index < 0)
> +		return prox_index;
> +
> +	msleep(isl29028_prox_data[prox_index].sleep_time);
>  
>  	return 0;
>  }
> @@ -361,7 +389,7 @@ static int isl29028_write_raw(struct iio_dev *indio_dev,
>  			break;
>  		}
>  
> -		ret = isl29028_set_proxim_sampling(chip, val);
> +		ret = isl29028_set_proxim_sampling(chip, val, val2);
>  		break;
>  	case IIO_LIGHT:
>  		if (mask != IIO_CHAN_INFO_SCALE) {
> @@ -439,7 +467,8 @@ static int isl29028_read_raw(struct iio_dev *indio_dev,
>  		if (chan->type != IIO_PROXIMITY)
>  			break;
>  
> -		*val = chip->prox_sampling;
> +		*val = chip->prox_sampling_int;
> +		*val2 = chip->prox_sampling_frac;
>  		ret = IIO_VAL_INT;
>  		break;
>  	case IIO_CHAN_INFO_SCALE:
> @@ -472,7 +501,7 @@ static int isl29028_read_raw(struct iio_dev *indio_dev,
>  }
>  
>  static IIO_CONST_ATTR(in_proximity_sampling_frequency_available,
> -				"1 3 5 10 13 20 83 100");
> +				"1.25 2.5 5 10 13.3 20 80 100");
>  static IIO_CONST_ATTR(in_illuminance_scale_available, "125 2000");
>  
>  #define ISL29028_CONST_ATTR(name) (&iio_const_attr_##name.dev_attr.attr)
> @@ -571,7 +600,8 @@ static int isl29028_probe(struct i2c_client *client,
>  	}
>  
>  	chip->enable_prox  = false;
> -	chip->prox_sampling = 20;
> +	chip->prox_sampling_int = 20;
> +	chip->prox_sampling_frac = 0;
>  	chip->lux_scale = 2000;
>  
>  	ret = regmap_write(chip->regmap, ISL29028_REG_TEST1_MODE, 0x0);
> 

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v3 2/2] staging: iio: isl29028: move out of staging
  2017-04-25  1:34 ` [PATCH v3 2/2] staging: iio: isl29028: move out of staging Brian Masney
@ 2017-04-26  5:30   ` Jonathan Cameron
  2017-04-26  5:49     ` Joe Perches
  0 siblings, 1 reply; 8+ messages in thread
From: Jonathan Cameron @ 2017-04-26  5:30 UTC (permalink / raw)
  To: Brian Masney, linux-iio
  Cc: gregkh, devel, knaack.h, lars, pmeerw, linux-kernel, ldewangan

On 25/04/17 02:34, Brian Masney wrote:
> Move ISL29028 ALS / Proximity Sensor out of staging and into mainline.
> 
> Signed-off-by: Brian Masney <masneyb@onstation.org>
Applied to the togreg branch of iio.git.

Thanks,

Jonathan
> ---
>  drivers/iio/light/Kconfig            |  10 +
>  drivers/iio/light/Makefile           |   1 +
>  drivers/iio/light/isl29028.c         | 723 +++++++++++++++++++++++++++++++++++
>  drivers/staging/iio/light/Kconfig    |  10 -
>  drivers/staging/iio/light/Makefile   |   1 -
>  drivers/staging/iio/light/isl29028.c | 723 -----------------------------------
>  6 files changed, 734 insertions(+), 734 deletions(-)
>  create mode 100644 drivers/iio/light/isl29028.c
>  delete mode 100644 drivers/staging/iio/light/isl29028.c
> 
> diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig
> index 33e755d..2356ed9 100644
> --- a/drivers/iio/light/Kconfig
> +++ b/drivers/iio/light/Kconfig
> @@ -172,6 +172,16 @@ config SENSORS_ISL29018
>  	 in lux, proximity infrared sensing and normal infrared sensing.
>  	 Data from sensor is accessible via sysfs.
>  
> +config SENSORS_ISL29028
> +	tristate "Intersil ISL29028 Concurrent Light and Proximity Sensor"
> +	depends on I2C
> +	select REGMAP_I2C
> +	help
> +	 Provides driver for the Intersil's ISL29028 device.
> +	 This driver supports the sysfs interface to get the ALS, IR intensity,
> +	 Proximity value via iio. The ISL29028 provides the concurrent sensing
> +	 of ambient light and proximity.
> +
>  config ISL29125
>  	tristate "Intersil ISL29125 digital color light sensor"
>  	depends on I2C
> diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile
> index 681363c..fa32fa4 100644
> --- a/drivers/iio/light/Makefile
> +++ b/drivers/iio/light/Makefile
> @@ -20,6 +20,7 @@ obj-$(CONFIG_GP2AP020A00F)	+= gp2ap020a00f.o
>  obj-$(CONFIG_HID_SENSOR_ALS)	+= hid-sensor-als.o
>  obj-$(CONFIG_HID_SENSOR_PROX)	+= hid-sensor-prox.o
>  obj-$(CONFIG_SENSORS_ISL29018)	+= isl29018.o
> +obj-$(CONFIG_SENSORS_ISL29028)	+= isl29028.o
>  obj-$(CONFIG_ISL29125)		+= isl29125.o
>  obj-$(CONFIG_JSA1212)		+= jsa1212.o
>  obj-$(CONFIG_SENSORS_LM3533)	+= lm3533-als.o
> diff --git a/drivers/iio/light/isl29028.c b/drivers/iio/light/isl29028.c
> new file mode 100644
> index 0000000..aeb5082
> --- /dev/null
> +++ b/drivers/iio/light/isl29028.c
> @@ -0,0 +1,723 @@
> +/*
> + * IIO driver for the light sensor ISL29028.
> + * ISL29028 is Concurrent Ambient Light and Proximity Sensor
> + *
> + * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
> + * Copyright (c) 2016-2017 Brian Masney <masneyb@onstation.org>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * 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, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/i2c.h>
> +#include <linux/err.h>
> +#include <linux/mutex.h>
> +#include <linux/delay.h>
> +#include <linux/slab.h>
> +#include <linux/regmap.h>
> +#include <linux/iio/iio.h>
> +#include <linux/iio/sysfs.h>
> +#include <linux/pm_runtime.h>
> +
> +#define ISL29028_CONV_TIME_MS			100
> +
> +#define ISL29028_REG_CONFIGURE			0x01
> +
> +#define ISL29028_CONF_ALS_IR_MODE_ALS		0
> +#define ISL29028_CONF_ALS_IR_MODE_IR		BIT(0)
> +#define ISL29028_CONF_ALS_IR_MODE_MASK		BIT(0)
> +
> +#define ISL29028_CONF_ALS_RANGE_LOW_LUX		0
> +#define ISL29028_CONF_ALS_RANGE_HIGH_LUX	BIT(1)
> +#define ISL29028_CONF_ALS_RANGE_MASK		BIT(1)
> +
> +#define ISL29028_CONF_ALS_DIS			0
> +#define ISL29028_CONF_ALS_EN			BIT(2)
> +#define ISL29028_CONF_ALS_EN_MASK		BIT(2)
> +
> +#define ISL29028_CONF_PROX_SLP_SH		4
> +#define ISL29028_CONF_PROX_SLP_MASK		(7 << ISL29028_CONF_PROX_SLP_SH)
> +
> +#define ISL29028_CONF_PROX_EN			BIT(7)
> +#define ISL29028_CONF_PROX_EN_MASK		BIT(7)
> +
> +#define ISL29028_REG_INTERRUPT			0x02
> +
> +#define ISL29028_REG_PROX_DATA			0x08
> +#define ISL29028_REG_ALSIR_L			0x09
> +#define ISL29028_REG_ALSIR_U			0x0A
> +
> +#define ISL29028_REG_TEST1_MODE			0x0E
> +#define ISL29028_REG_TEST2_MODE			0x0F
> +
> +#define ISL29028_NUM_REGS			(ISL29028_REG_TEST2_MODE + 1)
> +
> +#define ISL29028_POWER_OFF_DELAY_MS		2000
> +
> +struct isl29028_prox_data {
> +	int sampling_int;
> +	int sampling_fract;
> +	int sleep_time;
> +};
> +
> +static const struct isl29028_prox_data isl29028_prox_data[] = {
> +	{   1, 250000, 800 },
> +	{   2, 500000, 400 },
> +	{   5,      0, 200 },
> +	{  10,      0, 100 },
> +	{  13, 300000,  75 },
> +	{  20,      0,  50 },
> +	{  80,      0,  13 }, /*
> +			       * Note: Data sheet lists 12.5 ms sleep time.
> +			       * Round up a half millisecond for msleep().
> +			       */
> +	{ 100,  0,   0 }
> +};
> +
> +enum isl29028_als_ir_mode {
> +	ISL29028_MODE_NONE = 0,
> +	ISL29028_MODE_ALS,
> +	ISL29028_MODE_IR,
> +};
> +
> +struct isl29028_chip {
> +	struct mutex			lock;
> +	struct regmap			*regmap;
> +	int				prox_sampling_int;
> +	int				prox_sampling_frac;
> +	bool				enable_prox;
> +	int				lux_scale;
> +	enum isl29028_als_ir_mode	als_ir_mode;
> +};
> +
> +static int isl29028_find_prox_sleep_index(int sampling_int, int sampling_fract)
> +{
> +	int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(isl29028_prox_data); ++i) {
> +		if (isl29028_prox_data[i].sampling_int == sampling_int &&
> +		    isl29028_prox_data[i].sampling_fract == sampling_fract)
> +			return i;
> +	}
> +
> +	return -EINVAL;
> +}
> +
> +static int isl29028_set_proxim_sampling(struct isl29028_chip *chip,
> +					int sampling_int, int sampling_fract)
> +{
> +	struct device *dev = regmap_get_device(chip->regmap);
> +	int sleep_index, ret;
> +
> +	sleep_index = isl29028_find_prox_sleep_index(sampling_int,
> +						     sampling_fract);
> +	if (sleep_index < 0)
> +		return sleep_index;
> +
> +	ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
> +				 ISL29028_CONF_PROX_SLP_MASK,
> +				 sleep_index << ISL29028_CONF_PROX_SLP_SH);
> +
> +	if (ret < 0) {
> +		dev_err(dev, "%s(): Error %d setting the proximity sampling\n",
> +			__func__, ret);
> +		return ret;
> +	}
> +
> +	chip->prox_sampling_int = sampling_int;
> +	chip->prox_sampling_frac = sampling_fract;
> +
> +	return ret;
> +}
> +
> +static int isl29028_enable_proximity(struct isl29028_chip *chip)
> +{
> +	int prox_index, ret;
> +
> +	ret = isl29028_set_proxim_sampling(chip, chip->prox_sampling_int,
> +					   chip->prox_sampling_frac);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
> +				 ISL29028_CONF_PROX_EN_MASK,
> +				 ISL29028_CONF_PROX_EN);
> +	if (ret < 0)
> +		return ret;
> +
> +	/* Wait for conversion to be complete for first sample */
> +	prox_index = isl29028_find_prox_sleep_index(chip->prox_sampling_int,
> +						    chip->prox_sampling_frac);
> +	if (prox_index < 0)
> +		return prox_index;
> +
> +	msleep(isl29028_prox_data[prox_index].sleep_time);
> +
> +	return 0;
> +}
> +
> +static int isl29028_set_als_scale(struct isl29028_chip *chip, int lux_scale)
> +{
> +	struct device *dev = regmap_get_device(chip->regmap);
> +	int val = (lux_scale == 2000) ? ISL29028_CONF_ALS_RANGE_HIGH_LUX :
> +					ISL29028_CONF_ALS_RANGE_LOW_LUX;
> +	int ret;
> +
> +	ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
> +				 ISL29028_CONF_ALS_RANGE_MASK, val);
> +	if (ret < 0) {
> +		dev_err(dev, "%s(): Error %d setting the ALS scale\n", __func__,
> +			ret);
> +		return ret;
> +	}
> +
> +	chip->lux_scale = lux_scale;
> +
> +	return ret;
> +}
> +
> +static int isl29028_set_als_ir_mode(struct isl29028_chip *chip,
> +				    enum isl29028_als_ir_mode mode)
> +{
> +	int ret;
> +
> +	if (chip->als_ir_mode == mode)
> +		return 0;
> +
> +	ret = isl29028_set_als_scale(chip, chip->lux_scale);
> +	if (ret < 0)
> +		return ret;
> +
> +	switch (mode) {
> +	case ISL29028_MODE_ALS:
> +		ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
> +					 ISL29028_CONF_ALS_IR_MODE_MASK,
> +					 ISL29028_CONF_ALS_IR_MODE_ALS);
> +		if (ret < 0)
> +			return ret;
> +
> +		ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
> +					 ISL29028_CONF_ALS_RANGE_MASK,
> +					 ISL29028_CONF_ALS_RANGE_HIGH_LUX);
> +		break;
> +	case ISL29028_MODE_IR:
> +		ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
> +					 ISL29028_CONF_ALS_IR_MODE_MASK,
> +					 ISL29028_CONF_ALS_IR_MODE_IR);
> +		break;
> +	case ISL29028_MODE_NONE:
> +		return regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
> +					  ISL29028_CONF_ALS_EN_MASK,
> +					  ISL29028_CONF_ALS_DIS);
> +	}
> +
> +	if (ret < 0)
> +		return ret;
> +
> +	/* Enable the ALS/IR */
> +	ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
> +				 ISL29028_CONF_ALS_EN_MASK,
> +				 ISL29028_CONF_ALS_EN);
> +	if (ret < 0)
> +		return ret;
> +
> +	/* Need to wait for conversion time if ALS/IR mode enabled */
> +	msleep(ISL29028_CONV_TIME_MS);
> +
> +	chip->als_ir_mode = mode;
> +
> +	return 0;
> +}
> +
> +static int isl29028_read_als_ir(struct isl29028_chip *chip, int *als_ir)
> +{
> +	struct device *dev = regmap_get_device(chip->regmap);
> +	unsigned int lsb;
> +	unsigned int msb;
> +	int ret;
> +
> +	ret = regmap_read(chip->regmap, ISL29028_REG_ALSIR_L, &lsb);
> +	if (ret < 0) {
> +		dev_err(dev,
> +			"%s(): Error %d reading register ALSIR_L\n",
> +			__func__, ret);
> +		return ret;
> +	}
> +
> +	ret = regmap_read(chip->regmap, ISL29028_REG_ALSIR_U, &msb);
> +	if (ret < 0) {
> +		dev_err(dev,
> +			"%s(): Error %d reading register ALSIR_U\n",
> +			__func__, ret);
> +		return ret;
> +	}
> +
> +	*als_ir = ((msb & 0xF) << 8) | (lsb & 0xFF);
> +
> +	return 0;
> +}
> +
> +static int isl29028_read_proxim(struct isl29028_chip *chip, int *prox)
> +{
> +	struct device *dev = regmap_get_device(chip->regmap);
> +	unsigned int data;
> +	int ret;
> +
> +	if (!chip->enable_prox) {
> +		ret = isl29028_enable_proximity(chip);
> +		if (ret < 0)
> +			return ret;
> +
> +		chip->enable_prox = true;
> +	}
> +
> +	ret = regmap_read(chip->regmap, ISL29028_REG_PROX_DATA, &data);
> +	if (ret < 0) {
> +		dev_err(dev, "%s(): Error %d reading register PROX_DATA\n",
> +			__func__, ret);
> +		return ret;
> +	}
> +
> +	*prox = data;
> +
> +	return 0;
> +}
> +
> +static int isl29028_als_get(struct isl29028_chip *chip, int *als_data)
> +{
> +	struct device *dev = regmap_get_device(chip->regmap);
> +	int ret;
> +	int als_ir_data;
> +
> +	ret = isl29028_set_als_ir_mode(chip, ISL29028_MODE_ALS);
> +	if (ret < 0) {
> +		dev_err(dev, "%s(): Error %d enabling ALS mode\n", __func__,
> +			ret);
> +		return ret;
> +	}
> +
> +	ret = isl29028_read_als_ir(chip, &als_ir_data);
> +	if (ret < 0)
> +		return ret;
> +
> +	/*
> +	 * convert als data count to lux.
> +	 * if lux_scale = 125,  lux = count * 0.031
> +	 * if lux_scale = 2000, lux = count * 0.49
> +	 */
> +	if (chip->lux_scale == 125)
> +		als_ir_data = (als_ir_data * 31) / 1000;
> +	else
> +		als_ir_data = (als_ir_data * 49) / 100;
> +
> +	*als_data = als_ir_data;
> +
> +	return 0;
> +}
> +
> +static int isl29028_ir_get(struct isl29028_chip *chip, int *ir_data)
> +{
> +	struct device *dev = regmap_get_device(chip->regmap);
> +	int ret;
> +
> +	ret = isl29028_set_als_ir_mode(chip, ISL29028_MODE_IR);
> +	if (ret < 0) {
> +		dev_err(dev, "%s(): Error %d enabling IR mode\n", __func__,
> +			ret);
> +		return ret;
> +	}
> +
> +	return isl29028_read_als_ir(chip, ir_data);
> +}
> +
> +static int isl29028_set_pm_runtime_busy(struct isl29028_chip *chip, bool on)
> +{
> +	struct device *dev = regmap_get_device(chip->regmap);
> +	int ret;
> +
> +	if (on) {
> +		ret = pm_runtime_get_sync(dev);
> +		if (ret < 0)
> +			pm_runtime_put_noidle(dev);
> +	} else {
> +		pm_runtime_mark_last_busy(dev);
> +		ret = pm_runtime_put_autosuspend(dev);
> +	}
> +
> +	return ret;
> +}
> +
> +/* Channel IO */
> +static int isl29028_write_raw(struct iio_dev *indio_dev,
> +			      struct iio_chan_spec const *chan,
> +			      int val, int val2, long mask)
> +{
> +	struct isl29028_chip *chip = iio_priv(indio_dev);
> +	struct device *dev = regmap_get_device(chip->regmap);
> +	int ret;
> +
> +	ret = isl29028_set_pm_runtime_busy(chip, true);
> +	if (ret < 0)
> +		return ret;
> +
> +	mutex_lock(&chip->lock);
> +
> +	ret = -EINVAL;
> +	switch (chan->type) {
> +	case IIO_PROXIMITY:
> +		if (mask != IIO_CHAN_INFO_SAMP_FREQ) {
> +			dev_err(dev,
> +				"%s(): proximity: Mask value 0x%08lx is not supported\n",
> +				__func__, mask);
> +			break;
> +		}
> +
> +		if (val < 1 || val > 100) {
> +			dev_err(dev,
> +				"%s(): proximity: Sampling frequency %d is not in the range [1:100]\n",
> +				__func__, val);
> +			break;
> +		}
> +
> +		ret = isl29028_set_proxim_sampling(chip, val, val2);
> +		break;
> +	case IIO_LIGHT:
> +		if (mask != IIO_CHAN_INFO_SCALE) {
> +			dev_err(dev,
> +				"%s(): light: Mask value 0x%08lx is not supported\n",
> +				__func__, mask);
> +			break;
> +		}
> +
> +		if (val != 125 && val != 2000) {
> +			dev_err(dev,
> +				"%s(): light: Lux scale %d is not in the set {125, 2000}\n",
> +				__func__, val);
> +			break;
> +		}
> +
> +		ret = isl29028_set_als_scale(chip, val);
> +		break;
> +	default:
> +		dev_err(dev, "%s(): Unsupported channel type %x\n",
> +			__func__, chan->type);
> +		break;
> +	}
> +
> +	mutex_unlock(&chip->lock);
> +
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = isl29028_set_pm_runtime_busy(chip, false);
> +	if (ret < 0)
> +		return ret;
> +
> +	return ret;
> +}
> +
> +static int isl29028_read_raw(struct iio_dev *indio_dev,
> +			     struct iio_chan_spec const *chan,
> +			     int *val, int *val2, long mask)
> +{
> +	struct isl29028_chip *chip = iio_priv(indio_dev);
> +	struct device *dev = regmap_get_device(chip->regmap);
> +	int ret, pm_ret;
> +
> +	ret = isl29028_set_pm_runtime_busy(chip, true);
> +	if (ret < 0)
> +		return ret;
> +
> +	mutex_lock(&chip->lock);
> +
> +	ret = -EINVAL;
> +	switch (mask) {
> +	case IIO_CHAN_INFO_RAW:
> +	case IIO_CHAN_INFO_PROCESSED:
> +		switch (chan->type) {
> +		case IIO_LIGHT:
> +			ret = isl29028_als_get(chip, val);
> +			break;
> +		case IIO_INTENSITY:
> +			ret = isl29028_ir_get(chip, val);
> +			break;
> +		case IIO_PROXIMITY:
> +			ret = isl29028_read_proxim(chip, val);
> +			break;
> +		default:
> +			break;
> +		}
> +
> +		if (ret < 0)
> +			break;
> +
> +		ret = IIO_VAL_INT;
> +		break;
> +	case IIO_CHAN_INFO_SAMP_FREQ:
> +		if (chan->type != IIO_PROXIMITY)
> +			break;
> +
> +		*val = chip->prox_sampling_int;
> +		*val2 = chip->prox_sampling_frac;
> +		ret = IIO_VAL_INT;
> +		break;
> +	case IIO_CHAN_INFO_SCALE:
> +		if (chan->type != IIO_LIGHT)
> +			break;
> +		*val = chip->lux_scale;
> +		ret = IIO_VAL_INT;
> +		break;
> +	default:
> +		dev_err(dev, "%s(): mask value 0x%08lx is not supported\n",
> +			__func__, mask);
> +		break;
> +	}
> +
> +	mutex_unlock(&chip->lock);
> +
> +	if (ret < 0)
> +		return ret;
> +
> +	/**
> +	 * Preserve the ret variable if the call to
> +	 * isl29028_set_pm_runtime_busy() is successful so the reading
> +	 * (if applicable) is returned to user space.
> +	 */
> +	pm_ret = isl29028_set_pm_runtime_busy(chip, false);
> +	if (pm_ret < 0)
> +		return pm_ret;
> +
> +	return ret;
> +}
> +
> +static IIO_CONST_ATTR(in_proximity_sampling_frequency_available,
> +				"1.25 2.5 5 10 13.3 20 80 100");
> +static IIO_CONST_ATTR(in_illuminance_scale_available, "125 2000");
> +
> +#define ISL29028_CONST_ATTR(name) (&iio_const_attr_##name.dev_attr.attr)
> +static struct attribute *isl29028_attributes[] = {
> +	ISL29028_CONST_ATTR(in_proximity_sampling_frequency_available),
> +	ISL29028_CONST_ATTR(in_illuminance_scale_available),
> +	NULL,
> +};
> +
> +static const struct attribute_group isl29108_group = {
> +	.attrs = isl29028_attributes,
> +};
> +
> +static const struct iio_chan_spec isl29028_channels[] = {
> +	{
> +		.type = IIO_LIGHT,
> +		.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
> +		BIT(IIO_CHAN_INFO_SCALE),
> +	}, {
> +		.type = IIO_INTENSITY,
> +		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
> +	}, {
> +		.type = IIO_PROXIMITY,
> +		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
> +		BIT(IIO_CHAN_INFO_SAMP_FREQ),
> +	}
> +};
> +
> +static const struct iio_info isl29028_info = {
> +	.attrs = &isl29108_group,
> +	.driver_module = THIS_MODULE,
> +	.read_raw = isl29028_read_raw,
> +	.write_raw = isl29028_write_raw,
> +};
> +
> +static int isl29028_clear_configure_reg(struct isl29028_chip *chip)
> +{
> +	struct device *dev = regmap_get_device(chip->regmap);
> +	int ret;
> +
> +	ret = regmap_write(chip->regmap, ISL29028_REG_CONFIGURE, 0x0);
> +	if (ret < 0)
> +		dev_err(dev, "%s(): Error %d clearing the CONFIGURE register\n",
> +			__func__, ret);
> +
> +	chip->als_ir_mode = ISL29028_MODE_NONE;
> +	chip->enable_prox = false;
> +
> +	return ret;
> +}
> +
> +static bool isl29028_is_volatile_reg(struct device *dev, unsigned int reg)
> +{
> +	switch (reg) {
> +	case ISL29028_REG_INTERRUPT:
> +	case ISL29028_REG_PROX_DATA:
> +	case ISL29028_REG_ALSIR_L:
> +	case ISL29028_REG_ALSIR_U:
> +		return true;
> +	default:
> +		return false;
> +	}
> +}
> +
> +static const struct regmap_config isl29028_regmap_config = {
> +	.reg_bits = 8,
> +	.val_bits = 8,
> +	.volatile_reg = isl29028_is_volatile_reg,
> +	.max_register = ISL29028_NUM_REGS - 1,
> +	.num_reg_defaults_raw = ISL29028_NUM_REGS,
> +	.cache_type = REGCACHE_RBTREE,
> +};
> +
> +static int isl29028_probe(struct i2c_client *client,
> +			  const struct i2c_device_id *id)
> +{
> +	struct isl29028_chip *chip;
> +	struct iio_dev *indio_dev;
> +	int ret;
> +
> +	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip));
> +	if (!indio_dev)
> +		return -ENOMEM;
> +
> +	chip = iio_priv(indio_dev);
> +
> +	i2c_set_clientdata(client, indio_dev);
> +	mutex_init(&chip->lock);
> +
> +	chip->regmap = devm_regmap_init_i2c(client, &isl29028_regmap_config);
> +	if (IS_ERR(chip->regmap)) {
> +		ret = PTR_ERR(chip->regmap);
> +		dev_err(&client->dev, "%s: Error %d initializing regmap\n",
> +			__func__, ret);
> +		return ret;
> +	}
> +
> +	chip->enable_prox  = false;
> +	chip->prox_sampling_int = 20;
> +	chip->prox_sampling_frac = 0;
> +	chip->lux_scale = 2000;
> +
> +	ret = regmap_write(chip->regmap, ISL29028_REG_TEST1_MODE, 0x0);
> +	if (ret < 0) {
> +		dev_err(&client->dev,
> +			"%s(): Error %d writing to TEST1_MODE register\n",
> +			__func__, ret);
> +		return ret;
> +	}
> +
> +	ret = regmap_write(chip->regmap, ISL29028_REG_TEST2_MODE, 0x0);
> +	if (ret < 0) {
> +		dev_err(&client->dev,
> +			"%s(): Error %d writing to TEST2_MODE register\n",
> +			__func__, ret);
> +		return ret;
> +	}
> +
> +	ret = isl29028_clear_configure_reg(chip);
> +	if (ret < 0)
> +		return ret;
> +
> +	indio_dev->info = &isl29028_info;
> +	indio_dev->channels = isl29028_channels;
> +	indio_dev->num_channels = ARRAY_SIZE(isl29028_channels);
> +	indio_dev->name = id->name;
> +	indio_dev->dev.parent = &client->dev;
> +	indio_dev->modes = INDIO_DIRECT_MODE;
> +
> +	pm_runtime_enable(&client->dev);
> +	pm_runtime_set_autosuspend_delay(&client->dev,
> +					 ISL29028_POWER_OFF_DELAY_MS);
> +	pm_runtime_use_autosuspend(&client->dev);
> +
> +	ret = devm_iio_device_register(indio_dev->dev.parent, indio_dev);
> +	if (ret < 0) {
> +		dev_err(&client->dev,
> +			"%s(): iio registration failed with error %d\n",
> +			__func__, ret);
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int isl29028_remove(struct i2c_client *client)
> +{
> +	struct iio_dev *indio_dev = i2c_get_clientdata(client);
> +	struct isl29028_chip *chip = iio_priv(indio_dev);
> +
> +	iio_device_unregister(indio_dev);
> +
> +	pm_runtime_disable(&client->dev);
> +	pm_runtime_set_suspended(&client->dev);
> +	pm_runtime_put_noidle(&client->dev);
> +
> +	return isl29028_clear_configure_reg(chip);
> +}
> +
> +static int __maybe_unused isl29028_suspend(struct device *dev)
> +{
> +	struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
> +	struct isl29028_chip *chip = iio_priv(indio_dev);
> +	int ret;
> +
> +	mutex_lock(&chip->lock);
> +
> +	ret = isl29028_clear_configure_reg(chip);
> +
> +	mutex_unlock(&chip->lock);
> +
> +	return ret;
> +}
> +
> +static int __maybe_unused isl29028_resume(struct device *dev)
> +{
> +	/**
> +	 * The specific component (ALS/IR or proximity) will enable itself as
> +	 * needed the next time that the user requests a reading. This is done
> +	 * above in isl29028_set_als_ir_mode() and isl29028_enable_proximity().
> +	 */
> +	return 0;
> +}
> +
> +static const struct dev_pm_ops isl29028_pm_ops = {
> +	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
> +				pm_runtime_force_resume)
> +	SET_RUNTIME_PM_OPS(isl29028_suspend, isl29028_resume, NULL)
> +};
> +
> +static const struct i2c_device_id isl29028_id[] = {
> +	{"isl29028", 0},
> +	{}
> +};
> +MODULE_DEVICE_TABLE(i2c, isl29028_id);
> +
> +static const struct of_device_id isl29028_of_match[] = {
> +	{ .compatible = "isl,isl29028", }, /* for backward compat., don't use */
> +	{ .compatible = "isil,isl29028", },
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(of, isl29028_of_match);
> +
> +static struct i2c_driver isl29028_driver = {
> +	.driver  = {
> +		.name = "isl29028",
> +		.pm = &isl29028_pm_ops,
> +		.of_match_table = isl29028_of_match,
> +	},
> +	.probe	 = isl29028_probe,
> +	.remove  = isl29028_remove,
> +	.id_table = isl29028_id,
> +};
> +
> +module_i2c_driver(isl29028_driver);
> +
> +MODULE_DESCRIPTION("ISL29028 Ambient Light and Proximity Sensor driver");
> +MODULE_LICENSE("GPL v2");
> +MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
> diff --git a/drivers/staging/iio/light/Kconfig b/drivers/staging/iio/light/Kconfig
> index 4fbf629..aacb0ae 100644
> --- a/drivers/staging/iio/light/Kconfig
> +++ b/drivers/staging/iio/light/Kconfig
> @@ -3,16 +3,6 @@
>  #
>  menu "Light sensors"
>  
> -config SENSORS_ISL29028
> -	tristate "Intersil ISL29028 Concurrent Light and Proximity Sensor"
> -	depends on I2C
> -	select REGMAP_I2C
> -	help
> -	 Provides driver for the Intersil's ISL29028 device.
> -	 This driver supports the sysfs interface to get the ALS, IR intensity,
> -	 Proximity value via iio. The ISL29028 provides the concurrent sensing
> -	 of ambient light and proximity.
> -
>  config TSL2x7x
>  	tristate "TAOS TSL/TMD2x71 and TSL/TMD2x72 Family of light and proximity sensors"
>  	depends on I2C
> diff --git a/drivers/staging/iio/light/Makefile b/drivers/staging/iio/light/Makefile
> index f8693e9..10286c3 100644
> --- a/drivers/staging/iio/light/Makefile
> +++ b/drivers/staging/iio/light/Makefile
> @@ -2,5 +2,4 @@
>  # Makefile for industrial I/O Light sensors
>  #
>  
> -obj-$(CONFIG_SENSORS_ISL29028)	+= isl29028.o
>  obj-$(CONFIG_TSL2x7x)	+= tsl2x7x_core.o
> diff --git a/drivers/staging/iio/light/isl29028.c b/drivers/staging/iio/light/isl29028.c
> deleted file mode 100644
> index aeb5082..0000000
> --- a/drivers/staging/iio/light/isl29028.c
> +++ /dev/null
> @@ -1,723 +0,0 @@
> -/*
> - * IIO driver for the light sensor ISL29028.
> - * ISL29028 is Concurrent Ambient Light and Proximity Sensor
> - *
> - * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
> - * Copyright (c) 2016-2017 Brian Masney <masneyb@onstation.org>
> - *
> - * This program is free software; you can redistribute it and/or modify it
> - * under the terms and conditions of the GNU General Public License,
> - * version 2, as published by the Free Software Foundation.
> - *
> - * This program is distributed in the hope it will be useful, but WITHOUT
> - * 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, see <http://www.gnu.org/licenses/>.
> - */
> -
> -#include <linux/module.h>
> -#include <linux/i2c.h>
> -#include <linux/err.h>
> -#include <linux/mutex.h>
> -#include <linux/delay.h>
> -#include <linux/slab.h>
> -#include <linux/regmap.h>
> -#include <linux/iio/iio.h>
> -#include <linux/iio/sysfs.h>
> -#include <linux/pm_runtime.h>
> -
> -#define ISL29028_CONV_TIME_MS			100
> -
> -#define ISL29028_REG_CONFIGURE			0x01
> -
> -#define ISL29028_CONF_ALS_IR_MODE_ALS		0
> -#define ISL29028_CONF_ALS_IR_MODE_IR		BIT(0)
> -#define ISL29028_CONF_ALS_IR_MODE_MASK		BIT(0)
> -
> -#define ISL29028_CONF_ALS_RANGE_LOW_LUX		0
> -#define ISL29028_CONF_ALS_RANGE_HIGH_LUX	BIT(1)
> -#define ISL29028_CONF_ALS_RANGE_MASK		BIT(1)
> -
> -#define ISL29028_CONF_ALS_DIS			0
> -#define ISL29028_CONF_ALS_EN			BIT(2)
> -#define ISL29028_CONF_ALS_EN_MASK		BIT(2)
> -
> -#define ISL29028_CONF_PROX_SLP_SH		4
> -#define ISL29028_CONF_PROX_SLP_MASK		(7 << ISL29028_CONF_PROX_SLP_SH)
> -
> -#define ISL29028_CONF_PROX_EN			BIT(7)
> -#define ISL29028_CONF_PROX_EN_MASK		BIT(7)
> -
> -#define ISL29028_REG_INTERRUPT			0x02
> -
> -#define ISL29028_REG_PROX_DATA			0x08
> -#define ISL29028_REG_ALSIR_L			0x09
> -#define ISL29028_REG_ALSIR_U			0x0A
> -
> -#define ISL29028_REG_TEST1_MODE			0x0E
> -#define ISL29028_REG_TEST2_MODE			0x0F
> -
> -#define ISL29028_NUM_REGS			(ISL29028_REG_TEST2_MODE + 1)
> -
> -#define ISL29028_POWER_OFF_DELAY_MS		2000
> -
> -struct isl29028_prox_data {
> -	int sampling_int;
> -	int sampling_fract;
> -	int sleep_time;
> -};
> -
> -static const struct isl29028_prox_data isl29028_prox_data[] = {
> -	{   1, 250000, 800 },
> -	{   2, 500000, 400 },
> -	{   5,      0, 200 },
> -	{  10,      0, 100 },
> -	{  13, 300000,  75 },
> -	{  20,      0,  50 },
> -	{  80,      0,  13 }, /*
> -			       * Note: Data sheet lists 12.5 ms sleep time.
> -			       * Round up a half millisecond for msleep().
> -			       */
> -	{ 100,  0,   0 }
> -};
> -
> -enum isl29028_als_ir_mode {
> -	ISL29028_MODE_NONE = 0,
> -	ISL29028_MODE_ALS,
> -	ISL29028_MODE_IR,
> -};
> -
> -struct isl29028_chip {
> -	struct mutex			lock;
> -	struct regmap			*regmap;
> -	int				prox_sampling_int;
> -	int				prox_sampling_frac;
> -	bool				enable_prox;
> -	int				lux_scale;
> -	enum isl29028_als_ir_mode	als_ir_mode;
> -};
> -
> -static int isl29028_find_prox_sleep_index(int sampling_int, int sampling_fract)
> -{
> -	int i;
> -
> -	for (i = 0; i < ARRAY_SIZE(isl29028_prox_data); ++i) {
> -		if (isl29028_prox_data[i].sampling_int == sampling_int &&
> -		    isl29028_prox_data[i].sampling_fract == sampling_fract)
> -			return i;
> -	}
> -
> -	return -EINVAL;
> -}
> -
> -static int isl29028_set_proxim_sampling(struct isl29028_chip *chip,
> -					int sampling_int, int sampling_fract)
> -{
> -	struct device *dev = regmap_get_device(chip->regmap);
> -	int sleep_index, ret;
> -
> -	sleep_index = isl29028_find_prox_sleep_index(sampling_int,
> -						     sampling_fract);
> -	if (sleep_index < 0)
> -		return sleep_index;
> -
> -	ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
> -				 ISL29028_CONF_PROX_SLP_MASK,
> -				 sleep_index << ISL29028_CONF_PROX_SLP_SH);
> -
> -	if (ret < 0) {
> -		dev_err(dev, "%s(): Error %d setting the proximity sampling\n",
> -			__func__, ret);
> -		return ret;
> -	}
> -
> -	chip->prox_sampling_int = sampling_int;
> -	chip->prox_sampling_frac = sampling_fract;
> -
> -	return ret;
> -}
> -
> -static int isl29028_enable_proximity(struct isl29028_chip *chip)
> -{
> -	int prox_index, ret;
> -
> -	ret = isl29028_set_proxim_sampling(chip, chip->prox_sampling_int,
> -					   chip->prox_sampling_frac);
> -	if (ret < 0)
> -		return ret;
> -
> -	ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
> -				 ISL29028_CONF_PROX_EN_MASK,
> -				 ISL29028_CONF_PROX_EN);
> -	if (ret < 0)
> -		return ret;
> -
> -	/* Wait for conversion to be complete for first sample */
> -	prox_index = isl29028_find_prox_sleep_index(chip->prox_sampling_int,
> -						    chip->prox_sampling_frac);
> -	if (prox_index < 0)
> -		return prox_index;
> -
> -	msleep(isl29028_prox_data[prox_index].sleep_time);
> -
> -	return 0;
> -}
> -
> -static int isl29028_set_als_scale(struct isl29028_chip *chip, int lux_scale)
> -{
> -	struct device *dev = regmap_get_device(chip->regmap);
> -	int val = (lux_scale == 2000) ? ISL29028_CONF_ALS_RANGE_HIGH_LUX :
> -					ISL29028_CONF_ALS_RANGE_LOW_LUX;
> -	int ret;
> -
> -	ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
> -				 ISL29028_CONF_ALS_RANGE_MASK, val);
> -	if (ret < 0) {
> -		dev_err(dev, "%s(): Error %d setting the ALS scale\n", __func__,
> -			ret);
> -		return ret;
> -	}
> -
> -	chip->lux_scale = lux_scale;
> -
> -	return ret;
> -}
> -
> -static int isl29028_set_als_ir_mode(struct isl29028_chip *chip,
> -				    enum isl29028_als_ir_mode mode)
> -{
> -	int ret;
> -
> -	if (chip->als_ir_mode == mode)
> -		return 0;
> -
> -	ret = isl29028_set_als_scale(chip, chip->lux_scale);
> -	if (ret < 0)
> -		return ret;
> -
> -	switch (mode) {
> -	case ISL29028_MODE_ALS:
> -		ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
> -					 ISL29028_CONF_ALS_IR_MODE_MASK,
> -					 ISL29028_CONF_ALS_IR_MODE_ALS);
> -		if (ret < 0)
> -			return ret;
> -
> -		ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
> -					 ISL29028_CONF_ALS_RANGE_MASK,
> -					 ISL29028_CONF_ALS_RANGE_HIGH_LUX);
> -		break;
> -	case ISL29028_MODE_IR:
> -		ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
> -					 ISL29028_CONF_ALS_IR_MODE_MASK,
> -					 ISL29028_CONF_ALS_IR_MODE_IR);
> -		break;
> -	case ISL29028_MODE_NONE:
> -		return regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
> -					  ISL29028_CONF_ALS_EN_MASK,
> -					  ISL29028_CONF_ALS_DIS);
> -	}
> -
> -	if (ret < 0)
> -		return ret;
> -
> -	/* Enable the ALS/IR */
> -	ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
> -				 ISL29028_CONF_ALS_EN_MASK,
> -				 ISL29028_CONF_ALS_EN);
> -	if (ret < 0)
> -		return ret;
> -
> -	/* Need to wait for conversion time if ALS/IR mode enabled */
> -	msleep(ISL29028_CONV_TIME_MS);
> -
> -	chip->als_ir_mode = mode;
> -
> -	return 0;
> -}
> -
> -static int isl29028_read_als_ir(struct isl29028_chip *chip, int *als_ir)
> -{
> -	struct device *dev = regmap_get_device(chip->regmap);
> -	unsigned int lsb;
> -	unsigned int msb;
> -	int ret;
> -
> -	ret = regmap_read(chip->regmap, ISL29028_REG_ALSIR_L, &lsb);
> -	if (ret < 0) {
> -		dev_err(dev,
> -			"%s(): Error %d reading register ALSIR_L\n",
> -			__func__, ret);
> -		return ret;
> -	}
> -
> -	ret = regmap_read(chip->regmap, ISL29028_REG_ALSIR_U, &msb);
> -	if (ret < 0) {
> -		dev_err(dev,
> -			"%s(): Error %d reading register ALSIR_U\n",
> -			__func__, ret);
> -		return ret;
> -	}
> -
> -	*als_ir = ((msb & 0xF) << 8) | (lsb & 0xFF);
> -
> -	return 0;
> -}
> -
> -static int isl29028_read_proxim(struct isl29028_chip *chip, int *prox)
> -{
> -	struct device *dev = regmap_get_device(chip->regmap);
> -	unsigned int data;
> -	int ret;
> -
> -	if (!chip->enable_prox) {
> -		ret = isl29028_enable_proximity(chip);
> -		if (ret < 0)
> -			return ret;
> -
> -		chip->enable_prox = true;
> -	}
> -
> -	ret = regmap_read(chip->regmap, ISL29028_REG_PROX_DATA, &data);
> -	if (ret < 0) {
> -		dev_err(dev, "%s(): Error %d reading register PROX_DATA\n",
> -			__func__, ret);
> -		return ret;
> -	}
> -
> -	*prox = data;
> -
> -	return 0;
> -}
> -
> -static int isl29028_als_get(struct isl29028_chip *chip, int *als_data)
> -{
> -	struct device *dev = regmap_get_device(chip->regmap);
> -	int ret;
> -	int als_ir_data;
> -
> -	ret = isl29028_set_als_ir_mode(chip, ISL29028_MODE_ALS);
> -	if (ret < 0) {
> -		dev_err(dev, "%s(): Error %d enabling ALS mode\n", __func__,
> -			ret);
> -		return ret;
> -	}
> -
> -	ret = isl29028_read_als_ir(chip, &als_ir_data);
> -	if (ret < 0)
> -		return ret;
> -
> -	/*
> -	 * convert als data count to lux.
> -	 * if lux_scale = 125,  lux = count * 0.031
> -	 * if lux_scale = 2000, lux = count * 0.49
> -	 */
> -	if (chip->lux_scale == 125)
> -		als_ir_data = (als_ir_data * 31) / 1000;
> -	else
> -		als_ir_data = (als_ir_data * 49) / 100;
> -
> -	*als_data = als_ir_data;
> -
> -	return 0;
> -}
> -
> -static int isl29028_ir_get(struct isl29028_chip *chip, int *ir_data)
> -{
> -	struct device *dev = regmap_get_device(chip->regmap);
> -	int ret;
> -
> -	ret = isl29028_set_als_ir_mode(chip, ISL29028_MODE_IR);
> -	if (ret < 0) {
> -		dev_err(dev, "%s(): Error %d enabling IR mode\n", __func__,
> -			ret);
> -		return ret;
> -	}
> -
> -	return isl29028_read_als_ir(chip, ir_data);
> -}
> -
> -static int isl29028_set_pm_runtime_busy(struct isl29028_chip *chip, bool on)
> -{
> -	struct device *dev = regmap_get_device(chip->regmap);
> -	int ret;
> -
> -	if (on) {
> -		ret = pm_runtime_get_sync(dev);
> -		if (ret < 0)
> -			pm_runtime_put_noidle(dev);
> -	} else {
> -		pm_runtime_mark_last_busy(dev);
> -		ret = pm_runtime_put_autosuspend(dev);
> -	}
> -
> -	return ret;
> -}
> -
> -/* Channel IO */
> -static int isl29028_write_raw(struct iio_dev *indio_dev,
> -			      struct iio_chan_spec const *chan,
> -			      int val, int val2, long mask)
> -{
> -	struct isl29028_chip *chip = iio_priv(indio_dev);
> -	struct device *dev = regmap_get_device(chip->regmap);
> -	int ret;
> -
> -	ret = isl29028_set_pm_runtime_busy(chip, true);
> -	if (ret < 0)
> -		return ret;
> -
> -	mutex_lock(&chip->lock);
> -
> -	ret = -EINVAL;
> -	switch (chan->type) {
> -	case IIO_PROXIMITY:
> -		if (mask != IIO_CHAN_INFO_SAMP_FREQ) {
> -			dev_err(dev,
> -				"%s(): proximity: Mask value 0x%08lx is not supported\n",
> -				__func__, mask);
> -			break;
> -		}
> -
> -		if (val < 1 || val > 100) {
> -			dev_err(dev,
> -				"%s(): proximity: Sampling frequency %d is not in the range [1:100]\n",
> -				__func__, val);
> -			break;
> -		}
> -
> -		ret = isl29028_set_proxim_sampling(chip, val, val2);
> -		break;
> -	case IIO_LIGHT:
> -		if (mask != IIO_CHAN_INFO_SCALE) {
> -			dev_err(dev,
> -				"%s(): light: Mask value 0x%08lx is not supported\n",
> -				__func__, mask);
> -			break;
> -		}
> -
> -		if (val != 125 && val != 2000) {
> -			dev_err(dev,
> -				"%s(): light: Lux scale %d is not in the set {125, 2000}\n",
> -				__func__, val);
> -			break;
> -		}
> -
> -		ret = isl29028_set_als_scale(chip, val);
> -		break;
> -	default:
> -		dev_err(dev, "%s(): Unsupported channel type %x\n",
> -			__func__, chan->type);
> -		break;
> -	}
> -
> -	mutex_unlock(&chip->lock);
> -
> -	if (ret < 0)
> -		return ret;
> -
> -	ret = isl29028_set_pm_runtime_busy(chip, false);
> -	if (ret < 0)
> -		return ret;
> -
> -	return ret;
> -}
> -
> -static int isl29028_read_raw(struct iio_dev *indio_dev,
> -			     struct iio_chan_spec const *chan,
> -			     int *val, int *val2, long mask)
> -{
> -	struct isl29028_chip *chip = iio_priv(indio_dev);
> -	struct device *dev = regmap_get_device(chip->regmap);
> -	int ret, pm_ret;
> -
> -	ret = isl29028_set_pm_runtime_busy(chip, true);
> -	if (ret < 0)
> -		return ret;
> -
> -	mutex_lock(&chip->lock);
> -
> -	ret = -EINVAL;
> -	switch (mask) {
> -	case IIO_CHAN_INFO_RAW:
> -	case IIO_CHAN_INFO_PROCESSED:
> -		switch (chan->type) {
> -		case IIO_LIGHT:
> -			ret = isl29028_als_get(chip, val);
> -			break;
> -		case IIO_INTENSITY:
> -			ret = isl29028_ir_get(chip, val);
> -			break;
> -		case IIO_PROXIMITY:
> -			ret = isl29028_read_proxim(chip, val);
> -			break;
> -		default:
> -			break;
> -		}
> -
> -		if (ret < 0)
> -			break;
> -
> -		ret = IIO_VAL_INT;
> -		break;
> -	case IIO_CHAN_INFO_SAMP_FREQ:
> -		if (chan->type != IIO_PROXIMITY)
> -			break;
> -
> -		*val = chip->prox_sampling_int;
> -		*val2 = chip->prox_sampling_frac;
> -		ret = IIO_VAL_INT;
> -		break;
> -	case IIO_CHAN_INFO_SCALE:
> -		if (chan->type != IIO_LIGHT)
> -			break;
> -		*val = chip->lux_scale;
> -		ret = IIO_VAL_INT;
> -		break;
> -	default:
> -		dev_err(dev, "%s(): mask value 0x%08lx is not supported\n",
> -			__func__, mask);
> -		break;
> -	}
> -
> -	mutex_unlock(&chip->lock);
> -
> -	if (ret < 0)
> -		return ret;
> -
> -	/**
> -	 * Preserve the ret variable if the call to
> -	 * isl29028_set_pm_runtime_busy() is successful so the reading
> -	 * (if applicable) is returned to user space.
> -	 */
> -	pm_ret = isl29028_set_pm_runtime_busy(chip, false);
> -	if (pm_ret < 0)
> -		return pm_ret;
> -
> -	return ret;
> -}
> -
> -static IIO_CONST_ATTR(in_proximity_sampling_frequency_available,
> -				"1.25 2.5 5 10 13.3 20 80 100");
> -static IIO_CONST_ATTR(in_illuminance_scale_available, "125 2000");
> -
> -#define ISL29028_CONST_ATTR(name) (&iio_const_attr_##name.dev_attr.attr)
> -static struct attribute *isl29028_attributes[] = {
> -	ISL29028_CONST_ATTR(in_proximity_sampling_frequency_available),
> -	ISL29028_CONST_ATTR(in_illuminance_scale_available),
> -	NULL,
> -};
> -
> -static const struct attribute_group isl29108_group = {
> -	.attrs = isl29028_attributes,
> -};
> -
> -static const struct iio_chan_spec isl29028_channels[] = {
> -	{
> -		.type = IIO_LIGHT,
> -		.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
> -		BIT(IIO_CHAN_INFO_SCALE),
> -	}, {
> -		.type = IIO_INTENSITY,
> -		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
> -	}, {
> -		.type = IIO_PROXIMITY,
> -		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
> -		BIT(IIO_CHAN_INFO_SAMP_FREQ),
> -	}
> -};
> -
> -static const struct iio_info isl29028_info = {
> -	.attrs = &isl29108_group,
> -	.driver_module = THIS_MODULE,
> -	.read_raw = isl29028_read_raw,
> -	.write_raw = isl29028_write_raw,
> -};
> -
> -static int isl29028_clear_configure_reg(struct isl29028_chip *chip)
> -{
> -	struct device *dev = regmap_get_device(chip->regmap);
> -	int ret;
> -
> -	ret = regmap_write(chip->regmap, ISL29028_REG_CONFIGURE, 0x0);
> -	if (ret < 0)
> -		dev_err(dev, "%s(): Error %d clearing the CONFIGURE register\n",
> -			__func__, ret);
> -
> -	chip->als_ir_mode = ISL29028_MODE_NONE;
> -	chip->enable_prox = false;
> -
> -	return ret;
> -}
> -
> -static bool isl29028_is_volatile_reg(struct device *dev, unsigned int reg)
> -{
> -	switch (reg) {
> -	case ISL29028_REG_INTERRUPT:
> -	case ISL29028_REG_PROX_DATA:
> -	case ISL29028_REG_ALSIR_L:
> -	case ISL29028_REG_ALSIR_U:
> -		return true;
> -	default:
> -		return false;
> -	}
> -}
> -
> -static const struct regmap_config isl29028_regmap_config = {
> -	.reg_bits = 8,
> -	.val_bits = 8,
> -	.volatile_reg = isl29028_is_volatile_reg,
> -	.max_register = ISL29028_NUM_REGS - 1,
> -	.num_reg_defaults_raw = ISL29028_NUM_REGS,
> -	.cache_type = REGCACHE_RBTREE,
> -};
> -
> -static int isl29028_probe(struct i2c_client *client,
> -			  const struct i2c_device_id *id)
> -{
> -	struct isl29028_chip *chip;
> -	struct iio_dev *indio_dev;
> -	int ret;
> -
> -	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip));
> -	if (!indio_dev)
> -		return -ENOMEM;
> -
> -	chip = iio_priv(indio_dev);
> -
> -	i2c_set_clientdata(client, indio_dev);
> -	mutex_init(&chip->lock);
> -
> -	chip->regmap = devm_regmap_init_i2c(client, &isl29028_regmap_config);
> -	if (IS_ERR(chip->regmap)) {
> -		ret = PTR_ERR(chip->regmap);
> -		dev_err(&client->dev, "%s: Error %d initializing regmap\n",
> -			__func__, ret);
> -		return ret;
> -	}
> -
> -	chip->enable_prox  = false;
> -	chip->prox_sampling_int = 20;
> -	chip->prox_sampling_frac = 0;
> -	chip->lux_scale = 2000;
> -
> -	ret = regmap_write(chip->regmap, ISL29028_REG_TEST1_MODE, 0x0);
> -	if (ret < 0) {
> -		dev_err(&client->dev,
> -			"%s(): Error %d writing to TEST1_MODE register\n",
> -			__func__, ret);
> -		return ret;
> -	}
> -
> -	ret = regmap_write(chip->regmap, ISL29028_REG_TEST2_MODE, 0x0);
> -	if (ret < 0) {
> -		dev_err(&client->dev,
> -			"%s(): Error %d writing to TEST2_MODE register\n",
> -			__func__, ret);
> -		return ret;
> -	}
> -
> -	ret = isl29028_clear_configure_reg(chip);
> -	if (ret < 0)
> -		return ret;
> -
> -	indio_dev->info = &isl29028_info;
> -	indio_dev->channels = isl29028_channels;
> -	indio_dev->num_channels = ARRAY_SIZE(isl29028_channels);
> -	indio_dev->name = id->name;
> -	indio_dev->dev.parent = &client->dev;
> -	indio_dev->modes = INDIO_DIRECT_MODE;
> -
> -	pm_runtime_enable(&client->dev);
> -	pm_runtime_set_autosuspend_delay(&client->dev,
> -					 ISL29028_POWER_OFF_DELAY_MS);
> -	pm_runtime_use_autosuspend(&client->dev);
> -
> -	ret = devm_iio_device_register(indio_dev->dev.parent, indio_dev);
> -	if (ret < 0) {
> -		dev_err(&client->dev,
> -			"%s(): iio registration failed with error %d\n",
> -			__func__, ret);
> -		return ret;
> -	}
> -
> -	return 0;
> -}
> -
> -static int isl29028_remove(struct i2c_client *client)
> -{
> -	struct iio_dev *indio_dev = i2c_get_clientdata(client);
> -	struct isl29028_chip *chip = iio_priv(indio_dev);
> -
> -	iio_device_unregister(indio_dev);
> -
> -	pm_runtime_disable(&client->dev);
> -	pm_runtime_set_suspended(&client->dev);
> -	pm_runtime_put_noidle(&client->dev);
> -
> -	return isl29028_clear_configure_reg(chip);
> -}
> -
> -static int __maybe_unused isl29028_suspend(struct device *dev)
> -{
> -	struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
> -	struct isl29028_chip *chip = iio_priv(indio_dev);
> -	int ret;
> -
> -	mutex_lock(&chip->lock);
> -
> -	ret = isl29028_clear_configure_reg(chip);
> -
> -	mutex_unlock(&chip->lock);
> -
> -	return ret;
> -}
> -
> -static int __maybe_unused isl29028_resume(struct device *dev)
> -{
> -	/**
> -	 * The specific component (ALS/IR or proximity) will enable itself as
> -	 * needed the next time that the user requests a reading. This is done
> -	 * above in isl29028_set_als_ir_mode() and isl29028_enable_proximity().
> -	 */
> -	return 0;
> -}
> -
> -static const struct dev_pm_ops isl29028_pm_ops = {
> -	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
> -				pm_runtime_force_resume)
> -	SET_RUNTIME_PM_OPS(isl29028_suspend, isl29028_resume, NULL)
> -};
> -
> -static const struct i2c_device_id isl29028_id[] = {
> -	{"isl29028", 0},
> -	{}
> -};
> -MODULE_DEVICE_TABLE(i2c, isl29028_id);
> -
> -static const struct of_device_id isl29028_of_match[] = {
> -	{ .compatible = "isl,isl29028", }, /* for backward compat., don't use */
> -	{ .compatible = "isil,isl29028", },
> -	{ },
> -};
> -MODULE_DEVICE_TABLE(of, isl29028_of_match);
> -
> -static struct i2c_driver isl29028_driver = {
> -	.driver  = {
> -		.name = "isl29028",
> -		.pm = &isl29028_pm_ops,
> -		.of_match_table = isl29028_of_match,
> -	},
> -	.probe	 = isl29028_probe,
> -	.remove  = isl29028_remove,
> -	.id_table = isl29028_id,
> -};
> -
> -module_i2c_driver(isl29028_driver);
> -
> -MODULE_DESCRIPTION("ISL29028 Ambient Light and Proximity Sensor driver");
> -MODULE_LICENSE("GPL v2");
> -MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
> 

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v3 2/2] staging: iio: isl29028: move out of staging
  2017-04-26  5:30   ` Jonathan Cameron
@ 2017-04-26  5:49     ` Joe Perches
  2017-04-26  6:03       ` Jonathan Cameron
  0 siblings, 1 reply; 8+ messages in thread
From: Joe Perches @ 2017-04-26  5:49 UTC (permalink / raw)
  To: Jonathan Cameron, Brian Masney, linux-iio
  Cc: gregkh, devel, knaack.h, lars, pmeerw, linux-kernel, ldewangan

On Wed, 2017-04-26 at 06:30 +0100, Jonathan Cameron wrote:
> On 25/04/17 02:34, Brian Masney wrote:
> > Move ISL29028 ALS / Proximity Sensor out of staging and into mainline.
> > 
> > Signed-off-by: Brian Masney <masneyb@onstation.org>

Hey Brian.

Next time it's better to use git format-patch -M
to reduce the patch size and show renames.

> Applied to the togreg branch of iio.git.
> 
> Thanks,
> 
> Jonathan
> > ---
> >  drivers/iio/light/Kconfig            |  10 +
> >  drivers/iio/light/Makefile           |   1 +
> >  drivers/iio/light/isl29028.c         | 723 +++++++++++++++++++++++++++++++++++
> >  drivers/staging/iio/light/Kconfig    |  10 -
> >  drivers/staging/iio/light/Makefile   |   1 -
> >  drivers/staging/iio/light/isl29028.c | 723 -----------------------------------
> >  6 files changed, 734 insertions(+), 734 deletions(-)
> >  create mode 100644 drivers/iio/light/isl29028.c
> >  delete mode 100644 drivers/staging/iio/light/isl29028.c

[quoted the entire patch]

And Jonathan, please trim your replies a bit more.

Thanks.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v3 2/2] staging: iio: isl29028: move out of staging
  2017-04-26  5:49     ` Joe Perches
@ 2017-04-26  6:03       ` Jonathan Cameron
  0 siblings, 0 replies; 8+ messages in thread
From: Jonathan Cameron @ 2017-04-26  6:03 UTC (permalink / raw)
  To: Joe Perches, Brian Masney, linux-iio
  Cc: gregkh, devel, knaack.h, lars, pmeerw, linux-kernel, ldewangan

On 26/04/17 06:49, Joe Perches wrote:
> On Wed, 2017-04-26 at 06:30 +0100, Jonathan Cameron wrote:
>> On 25/04/17 02:34, Brian Masney wrote:
>>> Move ISL29028 ALS / Proximity Sensor out of staging and into mainline.
>>>
>>> Signed-off-by: Brian Masney <masneyb@onstation.org>
> 
> Hey Brian.
> 
> Next time it's better to use git format-patch -M
> to reduce the patch size and show renames.
My fault :)  For patches doing a move of an IIO driver
out of staging I've asked that people don't
use -M to encourage people to do a 'big picture' review
before we move them out of staging. 

This particular one went pretty smoothly, but in some other
staging move patches it's been a different story!

As Brian has done quite a few of these he is getting pretty
good at it ;)

Jonathan
> 
>> Applied to the togreg branch of iio.git
>>
>> Thanks,
>>
>> Jonathan
>>> ---
>>>  drivers/iio/light/Kconfig            |  10 +
>>>  drivers/iio/light/Makefile           |   1 +
>>>  drivers/iio/light/isl29028.c         | 723 +++++++++++++++++++++++++++++++++++
>>>  drivers/staging/iio/light/Kconfig    |  10 -
>>>  drivers/staging/iio/light/Makefile   |   1 -
>>>  drivers/staging/iio/light/isl29028.c | 723 -----------------------------------
>>>  6 files changed, 734 insertions(+), 734 deletions(-)
>>>  create mode 100644 drivers/iio/light/isl29028.c
>>>  delete mode 100644 drivers/staging/iio/light/isl29028.c
> 
> [quoted the entire patch]
> 
> And Jonathan, please trim your replies a bit more.
> 
> Thanks.
> 

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2017-04-26  6:04 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-04-25  1:34 [PATCH v3 0/2] staging: iio: isl29028: move out of staging Brian Masney
2017-04-25  1:34 ` [PATCH v3 1/2] staging: iio: isl29028: correct proximity sleep times Brian Masney
2017-04-26  5:30   ` Jonathan Cameron
2017-04-25  1:34 ` [PATCH v3 2/2] staging: iio: isl29028: move out of staging Brian Masney
2017-04-26  5:30   ` Jonathan Cameron
2017-04-26  5:49     ` Joe Perches
2017-04-26  6:03       ` Jonathan Cameron
2017-04-26  5:25 ` [PATCH v3 0/2] " Jonathan Cameron

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).