From: Jonathan Cameron <jic23@kernel.org>
To: Jeff LaBundy <jeff@labundy.com>
Cc: lee.jones@linaro.org, dmitry.torokhov@gmail.com,
jdelvare@suse.com, linux@roeck-us.net, thierry.reding@gmail.com,
devicetree@vger.kernel.org, linux-input@vger.kernel.org,
linux-hwmon@vger.kernel.org, u.kleine-koenig@pengutronix.de,
linux-pwm@vger.kernel.org, knaack.h@gmx.de, lars@metafoo.de,
pmeerw@pmeerw.net, linux-iio@vger.kernel.org, robh+dt@kernel.org,
mark.rutland@arm.com
Subject: Re: [PATCH 6/8] iio: light: Add support for Azoteq IQS621 ambient light sensor
Date: Tue, 22 Oct 2019 12:23:49 +0100 [thread overview]
Message-ID: <20191022121949.0b6b27d4@archlinux> (raw)
In-Reply-To: <1571631083-4962-7-git-send-email-jeff@labundy.com>
On Sun, 20 Oct 2019 23:11:21 -0500
Jeff LaBundy <jeff@labundy.com> wrote:
> This patch adds support for the Azoteq IQS621 ambient light sensor,
> capable of reporting intensity directly in units of lux.
If they are in lux, should be using IIO_CHAN_INFO_PROCESSED to indicate
that. I was wondering why we had no scale then noticed this comment.
Other than that, this looks good to me. So with that tidied up in V2.
Acked-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
One trivial comment to perhaps drop an error print as overly verbose inline.
>
> Signed-off-by: Jeff LaBundy <jeff@labundy.com>
> ---
> drivers/iio/light/Kconfig | 10 ++
> drivers/iio/light/Makefile | 1 +
> drivers/iio/light/iqs621-als.c | 361 +++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 372 insertions(+)
> create mode 100644 drivers/iio/light/iqs621-als.c
>
> diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig
> index 4a1a883..aad26dc 100644
> --- a/drivers/iio/light/Kconfig
> +++ b/drivers/iio/light/Kconfig
> @@ -162,6 +162,16 @@ config GP2AP020A00F
> To compile this driver as a module, choose M here: the
> module will be called gp2ap020a00f.
>
> +config IQS621_ALS
> + tristate "Azoteq IQS621 ambient light sensor"
> + depends on MFD_IQS62X
> + help
> + Say Y here if you want to build support for the Azoteq IQS621
> + ambient light sensor.
> +
> + To compile this driver as a module, choose M here: the module
> + will be called iqs621-als.
> +
> config SENSORS_ISL29018
> tristate "Intersil 29018 light and proximity sensor"
> depends on I2C
> diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile
> index 00d1f9b..aa34358 100644
> --- a/drivers/iio/light/Makefile
> +++ b/drivers/iio/light/Makefile
> @@ -20,6 +20,7 @@ obj-$(CONFIG_IIO_CROS_EC_LIGHT_PROX) += cros_ec_light_prox.o
> 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_IQS621_ALS) += iqs621-als.o
> obj-$(CONFIG_SENSORS_ISL29018) += isl29018.o
> obj-$(CONFIG_SENSORS_ISL29028) += isl29028.o
> obj-$(CONFIG_ISL29125) += isl29125.o
> diff --git a/drivers/iio/light/iqs621-als.c b/drivers/iio/light/iqs621-als.c
> new file mode 100644
> index 0000000..92a6173
> --- /dev/null
> +++ b/drivers/iio/light/iqs621-als.c
> @@ -0,0 +1,361 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Azoteq IQS621 Ambient Light Sensor
> + *
> + * Copyright (C) 2019
> + * Author: Jeff LaBundy <jeff@labundy.com>
> + */
> +
> +#include <linux/device.h>
> +#include <linux/iio/events.h>
> +#include <linux/iio/iio.h>
> +#include <linux/kernel.h>
> +#include <linux/mfd/iqs62x.h>
> +#include <linux/module.h>
> +#include <linux/mutex.h>
> +#include <linux/notifier.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +
> +#define IQS621_ALS_FLAGS 0x16
> +#define IQS621_ALS_FLAGS_LIGHT BIT(7)
> +
> +#define IQS621_ALS_UI_OUT 0x17
> +
> +#define IQS621_ALS_THRESH_DARK 0x80
> +#define IQS621_ALS_THRESH_DARK_MAX 1020
> +#define IQS621_ALS_THRESH_DARK_SHIFT 2
> +
> +#define IQS621_ALS_THRESH_LIGHT 0x81
> +#define IQS621_ALS_THRESH_LIGHT_MAX 4080
> +#define IQS621_ALS_THRESH_LIGHT_SHIFT 4
> +
> +struct iqs621_als_private {
> + struct iqs62x_core *iqs62x;
> + struct notifier_block notifier;
> + struct mutex lock;
> + bool event_en;
> + u8 thresh_light;
> + u8 thresh_dark;
> + u8 flags;
> +};
> +
> +static int iqs621_als_init(struct iqs621_als_private *iqs621_als)
> +{
> + struct iqs62x_core *iqs62x = iqs621_als->iqs62x;
> + unsigned int val;
> + int error;
> +
> + mutex_lock(&iqs621_als->lock);
> +
> + error = regmap_write(iqs62x->map, IQS621_ALS_THRESH_LIGHT,
> + iqs621_als->thresh_light);
> + if (error)
> + goto err_mutex;
> +
> + error = regmap_write(iqs62x->map, IQS621_ALS_THRESH_DARK,
> + iqs621_als->thresh_dark);
> + if (error)
> + goto err_mutex;
> +
> + error = regmap_read(iqs62x->map, IQS621_ALS_FLAGS, &val);
> + if (error)
> + goto err_mutex;
> + iqs621_als->flags = val;
> +
> + error = regmap_update_bits(iqs62x->map, IQS620_GLBL_EVENT_MASK,
> + iqs62x->dev_desc->als_mask,
> + iqs621_als->event_en ? 0 : 0xFF);
> +
> +err_mutex:
> + mutex_unlock(&iqs621_als->lock);
> +
> + return error;
> +}
> +
> +static int iqs621_als_notifier(struct notifier_block *notifier,
> + unsigned long event_flags, void *context)
> +{
> + struct iqs62x_event_data *event_data = context;
> + struct iqs621_als_private *iqs621_als;
> + struct iio_dev *indio_dev;
> + enum iio_event_direction dir;
> + int error;
> +
> + iqs621_als = container_of(notifier, struct iqs621_als_private,
> + notifier);
> + indio_dev = iio_priv_to_dev(iqs621_als);
> +
> + if (event_flags & BIT(IQS62X_EVENT_SYS_RESET)) {
> + error = iqs621_als_init(iqs621_als);
> + if (error) {
> + dev_err(indio_dev->dev.parent,
> + "Failed to re-initialize device: %d\n", error);
> + return NOTIFY_BAD;
> + }
> +
> + return NOTIFY_OK;
> + }
> +
> + if (!((event_data->als_flags ^ iqs621_als->flags) &
> + IQS621_ALS_FLAGS_LIGHT))
> + return NOTIFY_DONE;
> +
> + iqs621_als->flags = event_data->als_flags;
> +
> + if (!iqs621_als->event_en)
> + return NOTIFY_OK;
> +
> + dir = iqs621_als->flags & IQS621_ALS_FLAGS_LIGHT ? IIO_EV_DIR_RISING :
> + IIO_EV_DIR_FALLING;
> +
> + iio_push_event(indio_dev,
> + IIO_UNMOD_EVENT_CODE(IIO_LIGHT, 0,
> + IIO_EV_TYPE_THRESH, dir),
> + iio_get_time_ns(indio_dev));
> +
> + return NOTIFY_OK;
> +}
> +
> +static void iqs621_als_notifier_unregister(void *context)
> +{
> + struct iqs621_als_private *iqs621_als = context;
> + struct iio_dev *indio_dev = iio_priv_to_dev(iqs621_als);
> + int error;
> +
> + error = blocking_notifier_chain_unregister(&iqs621_als->iqs62x->nh,
> + &iqs621_als->notifier);
> + if (error)
> + dev_err(indio_dev->dev.parent,
> + "Failed to unregister notifier: %d\n", error);
> +}
> +
> +static int iqs621_als_read_raw(struct iio_dev *indio_dev,
> + struct iio_chan_spec const *chan,
> + int *val, int *val2, long mask)
> +{
> + struct iqs621_als_private *iqs621_als = iio_priv(indio_dev);
> + struct iqs62x_core *iqs62x = iqs621_als->iqs62x;
> + int error;
> + __le16 val_buf;
> +
> + switch (mask) {
> + case IIO_CHAN_INFO_RAW:
> + error = regmap_raw_read(iqs62x->map, IQS621_ALS_UI_OUT,
> + &val_buf, sizeof(val_buf));
> + if (error)
> + return error;
> +
> + *val = le16_to_cpu(val_buf);
> + return IIO_VAL_INT;
> +
> + default:
> + return -EINVAL;
> + }
> +}
> +
> +static int iqs621_als_read_event_config(struct iio_dev *indio_dev,
> + const struct iio_chan_spec *chan,
> + enum iio_event_type type,
> + enum iio_event_direction dir)
> +{
> + struct iqs621_als_private *iqs621_als = iio_priv(indio_dev);
> +
> + return iqs621_als->event_en;
> +}
> +
> +static int iqs621_als_write_event_config(struct iio_dev *indio_dev,
> + const struct iio_chan_spec *chan,
> + enum iio_event_type type,
> + enum iio_event_direction dir,
> + int state)
> +{
> + struct iqs621_als_private *iqs621_als = iio_priv(indio_dev);
> + struct iqs62x_core *iqs62x = iqs621_als->iqs62x;
> + int error;
> +
> + mutex_lock(&iqs621_als->lock);
> +
> + error = regmap_update_bits(iqs62x->map, IQS620_GLBL_EVENT_MASK,
> + iqs62x->dev_desc->als_mask,
> + state ? 0 : 0xFF);
> + if (!error)
> + iqs621_als->event_en = state;
> +
> + mutex_unlock(&iqs621_als->lock);
> +
> + return error;
> +}
> +
> +static int iqs621_als_read_event_value(struct iio_dev *indio_dev,
> + const struct iio_chan_spec *chan,
> + enum iio_event_type type,
> + enum iio_event_direction dir,
> + enum iio_event_info info,
> + int *val, int *val2)
> +{
> + struct iqs621_als_private *iqs621_als = iio_priv(indio_dev);
> +
> + switch (dir) {
> + case IIO_EV_DIR_RISING:
> + *val = iqs621_als->thresh_light;
> + *val <<= IQS621_ALS_THRESH_LIGHT_SHIFT;
> + return IIO_VAL_INT;
> +
> + case IIO_EV_DIR_FALLING:
> + *val = iqs621_als->thresh_dark;
> + *val <<= IQS621_ALS_THRESH_DARK_SHIFT;
> + return IIO_VAL_INT;
> +
> + default:
> + return -EINVAL;
> + }
> +}
> +
> +static int iqs621_als_write_event_value(struct iio_dev *indio_dev,
> + const struct iio_chan_spec *chan,
> + enum iio_event_type type,
> + enum iio_event_direction dir,
> + enum iio_event_info info,
> + int val, int val2)
> +{
> + struct iqs621_als_private *iqs621_als = iio_priv(indio_dev);
> + struct iqs62x_core *iqs62x = iqs621_als->iqs62x;
> + int error = -EINVAL;
> +
> + mutex_lock(&iqs621_als->lock);
> +
> + switch (dir) {
> + case IIO_EV_DIR_RISING:
> + if (val > IQS621_ALS_THRESH_LIGHT_MAX)
> + break;
> + val >>= IQS621_ALS_THRESH_LIGHT_SHIFT;
> +
> + error = regmap_write(iqs62x->map, IQS621_ALS_THRESH_LIGHT, val);
> + if (!error)
> + iqs621_als->thresh_light = val;
> + break;
> +
> + case IIO_EV_DIR_FALLING:
> + if (val > IQS621_ALS_THRESH_DARK)
> + break;
> + val >>= IQS621_ALS_THRESH_DARK_SHIFT;
> +
> + error = regmap_write(iqs62x->map, IQS621_ALS_THRESH_DARK, val);
> + if (!error)
> + iqs621_als->thresh_dark = val;
> + break;
> +
> + default:
> + break;
> + }
> +
> + mutex_unlock(&iqs621_als->lock);
> +
> + return error;
> +}
> +
> +static const struct iio_info iqs621_als_info = {
> + .read_raw = &iqs621_als_read_raw,
> + .read_event_config = iqs621_als_read_event_config,
> + .write_event_config = iqs621_als_write_event_config,
> + .read_event_value = iqs621_als_read_event_value,
> + .write_event_value = iqs621_als_write_event_value,
> +};
> +
> +static const struct iio_event_spec iqs621_als_events[] = {
> + {
> + .type = IIO_EV_TYPE_THRESH,
> + .dir = IIO_EV_DIR_EITHER,
> + .mask_separate = BIT(IIO_EV_INFO_ENABLE),
> + },
> + {
> + .type = IIO_EV_TYPE_THRESH,
> + .dir = IIO_EV_DIR_RISING,
> + .mask_separate = BIT(IIO_EV_INFO_VALUE),
> + },
> + {
> + .type = IIO_EV_TYPE_THRESH,
> + .dir = IIO_EV_DIR_FALLING,
> + .mask_separate = BIT(IIO_EV_INFO_VALUE),
> + },
> +};
> +
> +static const struct iio_chan_spec iqs621_als_channels[] = {
> + {
> + .type = IIO_LIGHT,
> + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
> + .event_spec = iqs621_als_events,
> + .num_event_specs = ARRAY_SIZE(iqs621_als_events),
> + },
> +};
> +
> +static int iqs621_als_probe(struct platform_device *pdev)
> +{
> + struct iqs62x_core *iqs62x = dev_get_drvdata(pdev->dev.parent);
> + struct iqs621_als_private *iqs621_als;
> + struct iio_dev *indio_dev;
> + unsigned int val;
> + int error;
> +
> + indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*iqs621_als));
> + if (!indio_dev)
> + return -ENOMEM;
> +
> + indio_dev->modes = INDIO_DIRECT_MODE;
> + indio_dev->dev.parent = &pdev->dev;
> + indio_dev->channels = iqs621_als_channels;
> + indio_dev->num_channels = ARRAY_SIZE(iqs621_als_channels);
> + indio_dev->name = iqs62x->dev_desc->dev_name;
> + indio_dev->info = &iqs621_als_info;
> +
> + iqs621_als = iio_priv(indio_dev);
> + iqs621_als->iqs62x = iqs62x;
> +
> + error = regmap_read(iqs62x->map, IQS621_ALS_THRESH_LIGHT, &val);
> + if (error)
> + return error;
> + iqs621_als->thresh_light = val;
> +
> + error = regmap_read(iqs62x->map, IQS621_ALS_THRESH_DARK, &val);
> + if (error)
> + return error;
> + iqs621_als->thresh_dark = val;
> +
> + mutex_init(&iqs621_als->lock);
> +
> + error = iqs621_als_init(iqs621_als);
> + if (error)
> + return error;
> +
> + iqs621_als->notifier.notifier_call = iqs621_als_notifier;
> + error = blocking_notifier_chain_register(&iqs621_als->iqs62x->nh,
> + &iqs621_als->notifier);
> + if (error) {
> + dev_err(&pdev->dev, "Failed to register notifier: %d\n", error);
> + return error;
> + }
> +
> + error = devm_add_action_or_reset(&pdev->dev,
> + iqs621_als_notifier_unregister,
> + iqs621_als);
> + if (error) {
This one can only fail if a memory allocation fails (IIRC) so it feels
a bit paranoid to worry about this little corner case when you are
fairly (correctly in my view) sparse in error message for other cases..
> + dev_err(&pdev->dev, "Failed to add action: %d\n", error);
> + return error;
> + }
> +
> + return devm_iio_device_register(&pdev->dev, indio_dev);
> +}
> +
> +static struct platform_driver iqs621_als_platform_driver = {
> + .driver = {
> + .name = IQS621_DRV_NAME_ALS,
> + },
> + .probe = iqs621_als_probe,
> +};
> +module_platform_driver(iqs621_als_platform_driver);
> +
> +MODULE_AUTHOR("Jeff LaBundy <jeff@labundy.com>");
> +MODULE_DESCRIPTION("Azoteq IQS621 Ambient Light Sensor");
> +MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:" IQS621_DRV_NAME_ALS);
next prev parent reply other threads:[~2019-10-22 11:39 UTC|newest]
Thread overview: 37+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-10-21 4:11 [PATCH 0/8] Add support for Azoteq IQS620A/621/622/624/625 Jeff LaBundy
2019-10-21 4:11 ` [PATCH 1/8] dt-bindings: mfd: iqs62x: Add bindings Jeff LaBundy
2019-10-22 11:00 ` Jonathan Cameron
2019-10-23 3:36 ` Jeff LaBundy
2019-10-23 9:30 ` Lee Jones
2019-10-24 2:38 ` Jeff LaBundy
2019-10-21 4:11 ` [PATCH 2/8] mfd: Add support for Azoteq IQS620A/621/622/624/625 Jeff LaBundy
2019-10-31 13:44 ` Lee Jones
2019-10-31 18:42 ` Dmitry Torokhov
2019-11-01 4:59 ` Jeff LaBundy
2019-11-01 8:56 ` Lee Jones
2019-11-02 2:49 ` Jeff LaBundy
2019-10-21 4:11 ` [PATCH 3/8] input: keyboard: " Jeff LaBundy
2019-10-23 0:22 ` Dmitry Torokhov
2019-10-23 1:29 ` Jeff LaBundy
2019-10-23 23:08 ` Dmitry Torokhov
2019-10-21 4:11 ` [PATCH 4/8] hwmon: Add support for Azoteq IQS620AT temperature sensor Jeff LaBundy
2019-10-21 15:38 ` Guenter Roeck
2019-10-22 2:26 ` Jeff LaBundy
2019-10-22 3:22 ` Guenter Roeck
2019-10-22 11:38 ` Jonathan Cameron
2019-10-23 2:04 ` Jeff LaBundy
2019-10-21 4:11 ` [PATCH 5/8] pwm: Add support for Azoteq IQS620A PWM generator Jeff LaBundy
2019-10-21 7:34 ` Uwe Kleine-König
2019-10-22 4:36 ` Jeff LaBundy
2019-10-22 6:54 ` Uwe Kleine-König
2019-10-23 2:45 ` Jeff LaBundy
2019-10-23 7:23 ` Uwe Kleine-König
2019-10-24 3:02 ` Jeff LaBundy
2019-10-21 4:11 ` [PATCH 6/8] iio: light: Add support for Azoteq IQS621 ambient light sensor Jeff LaBundy
2019-10-22 11:23 ` Jonathan Cameron [this message]
2019-10-23 2:59 ` Jeff LaBundy
2019-10-21 4:11 ` [PATCH 7/8] iio: proximity: Add support for Azoteq IQS622 proximity sensor Jeff LaBundy
2019-10-22 11:23 ` Jonathan Cameron
2019-10-23 3:09 ` Jeff LaBundy
2019-10-21 4:11 ` [PATCH 8/8] iio: position: Add support for Azoteq IQS624/625 angle sensor Jeff LaBundy
2019-10-22 11:28 ` Jonathan Cameron
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20191022121949.0b6b27d4@archlinux \
--to=jic23@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=dmitry.torokhov@gmail.com \
--cc=jdelvare@suse.com \
--cc=jeff@labundy.com \
--cc=knaack.h@gmx.de \
--cc=lars@metafoo.de \
--cc=lee.jones@linaro.org \
--cc=linux-hwmon@vger.kernel.org \
--cc=linux-iio@vger.kernel.org \
--cc=linux-input@vger.kernel.org \
--cc=linux-pwm@vger.kernel.org \
--cc=linux@roeck-us.net \
--cc=mark.rutland@arm.com \
--cc=pmeerw@pmeerw.net \
--cc=robh+dt@kernel.org \
--cc=thierry.reding@gmail.com \
--cc=u.kleine-koenig@pengutronix.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.