From: Jesper X Nilsson <jesper.x.nilsson@axis.com>
To: "Jonathan Cameron" <jic23@kernel.org>,
"David Lechner" <dlechner@baylibre.com>,
"Nuno Sá" <nuno.sa@analog.com>,
"Andy Shevchenko" <andy@kernel.org>,
"Rob Herring" <robh@kernel.org>,
"Krzysztof Kozlowski" <krzk+dt@kernel.org>,
"Conor Dooley" <conor+dt@kernel.org>,
"Stefan Windfeldt-Prytz" <stefan.windfeldt-prytz@axis.com>
Cc: <linux-iio@vger.kernel.org>, <devicetree@vger.kernel.org>,
<linux-kernel@vger.kernel.org>,
Jesper X Nilsson <jesper.x.nilsson@axis.com>, <kernel@axis.com>
Subject: [PATCH v2 4/4] iio: light: opt4001: add support for opt4041
Date: Fri, 23 Oct 2026 14:30:31 +0200 [thread overview]
Message-ID: <20261023-opt4041-v2-4-ee320812804c@axis.com> (raw)
In-Reply-To: <20261023-opt4041-v2-0-ee320812804c@axis.com>
Extend the opt4001 driver to also support OPT4041. The devices are very
similar, with the difference being OPT4041 having two channels, one
visible and one wide band channel ranging from 380nm to 1000nm.
The register map is almost the same. OPT4001 has registers to read out
the last four values sampled. OPT4041 maps to the same registers, but
has two channels, saving the last two samples for each channel.
Datasheet: https://www.ti.com/lit/gpn/opt4041
Signed-off-by: Jesper X Nilsson <jesper.x.nilsson@axis.com>
---
drivers/iio/light/Kconfig | 6 +++--
drivers/iio/light/opt4001.c | 66 ++++++++++++++++++++++++++++++++++++++++++---
2 files changed, 66 insertions(+), 6 deletions(-)
diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig
index 462fff1ddef2..26c3fa057a38 100644
--- a/drivers/iio/light/Kconfig
+++ b/drivers/iio/light/Kconfig
@@ -503,12 +503,14 @@ config OPT3001
opt3001.
config OPT4001
- tristate "Texas Instruments OPT4001 Light Sensor"
+ tristate "Texas Instruments OPT4001 and compatible Light Sensors"
depends on I2C
select REGMAP_I2C
help
If you say Y or M here, you get support for Texas Instruments
- OPT4001 Ambient Light Sensor.
+ Ambient Light Sensors:
+ - OPT4001
+ - OPT4041
If built as a dynamically linked module, it will be called
opt4001.
diff --git a/drivers/iio/light/opt4001.c b/drivers/iio/light/opt4001.c
index dc2eac8ad4af..5dcf9fe0aaad 100644
--- a/drivers/iio/light/opt4001.c
+++ b/drivers/iio/light/opt4001.c
@@ -2,9 +2,11 @@
/*
* Copyright (C) 2023 Axis Communications AB
*
- * Datasheet: https://www.ti.com/lit/gpn/opt4001
+ * Datasheets:
+ * https://www.ti.com/lit/gpn/opt4001
+ * https://www.ti.com/lit/gpn/opt4041
*
- * Device driver for the Texas Instruments OPT4001.
+ * Texas Instruments OPT4001 and compatible Light Sensors
*/
#include <linux/bitfield.h>
@@ -19,6 +21,8 @@
/* OPT4001 register set */
#define OPT4001_LIGHT1_MSB 0x00
#define OPT4001_LIGHT1_LSB 0x01
+#define OPT4041_LIGHT2_MSB 0x02
+#define OPT4041_LIGHT2_LSB 0x03
#define OPT4001_CTRL 0x0A
#define OPT4001_DEVICE_ID 0x11
@@ -43,6 +47,7 @@
/* OPT4001 constants */
#define OPT4001_DEVICE_ID_VAL 0x121
+#define OPT4041_DEVICE_ID_VAL 0x221
/* OPT4001 operating modes */
#define OPT4001_CTRL_OPER_MODE_OFF 0x0
@@ -72,7 +77,7 @@
/*
* The different packaging of OPT4001 has different constants used when calculating
- * lux values.
+ * lux values and OPT4041 has one additional wide band channel.
*/
struct opt4001_chip_info {
struct s32_fract ratio;
@@ -99,6 +104,25 @@ static const struct iio_chan_spec opt4001_channels[] = {
},
};
+static const struct iio_chan_spec opt4041_channels[] = {
+ {
+ .type = IIO_LIGHT,
+ .address = OPT4001_LIGHT1_MSB,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+ .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME),
+ },
+ {
+ .type = IIO_INTENSITY,
+ .modified = 1,
+ .channel2 = IIO_MOD_LIGHT_BOTH,
+ .address = OPT4041_LIGHT2_MSB,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME),
+ },
+};
+
static const struct opt4001_chip_info opt4001_sot_5x3_info = {
.ratio = { .numerator = 4375, .denominator = 10000000 },
.name = "opt4001-sot-5x3",
@@ -115,6 +139,14 @@ static const struct opt4001_chip_info opt4001_picostar_info = {
.device_id = OPT4001_DEVICE_ID_VAL,
};
+static const struct opt4001_chip_info opt4041_sot_5x3_info = {
+ .ratio = {.numerator = 5850, .denominator = 10000000 },
+ .name = "opt4041-sot-5x3",
+ .channels = opt4041_channels,
+ .num_channels = ARRAY_SIZE(opt4041_channels),
+ .device_id = OPT4041_DEVICE_ID_VAL,
+};
+
static const int opt4001_int_time_available[][2] = {
{ 0, 600 },
{ 0, 1000 },
@@ -267,10 +299,30 @@ static int opt4001_read_raw(struct iio_dev *indio_dev,
int *val, int *val2, long mask)
{
struct opt4001_chip *chip = iio_priv(indio_dev);
+ u64 raw_value;
+ u32 rem;
+ int ret;
switch (mask) {
case IIO_CHAN_INFO_PROCESSED:
return opt4001_read_lux_value(chip, chan->address, val, val2);
+ case IIO_CHAN_INFO_RAW:
+ ret = opt4001_read_raw_value(chip, chan->address, &raw_value);
+ if (ret)
+ return ret;
+
+ *val = div_u64_rem(raw_value, 100, &rem);
+ *val2 = rem * 10000;
+ return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_CHAN_INFO_SCALE:
+ /*
+ * OPT4041 CH1: datasheet specifies 0.1923 nW/cm^2 per ADC code
+ * with a 520 nm stimulus. Convert to nW/m^2 (x10000) and
+ * compensate for dividing the reported raw value by 100 (x100).
+ * The resulting scale is 192300 nW/m^2 per reported unit.
+ */
+ *val = 192300;
+ return IIO_VAL_INT;
case IIO_CHAN_INFO_INT_TIME:
*val = 0;
*val2 = opt4001_int_time_reg[chip->int_time][0];
@@ -337,6 +389,8 @@ static bool opt4001_readable_reg(struct device *dev, unsigned int reg)
switch (reg) {
case OPT4001_LIGHT1_MSB:
case OPT4001_LIGHT1_LSB:
+ case OPT4041_LIGHT2_MSB:
+ case OPT4041_LIGHT2_LSB:
case OPT4001_CTRL:
case OPT4001_DEVICE_ID:
return true;
@@ -360,6 +414,8 @@ static bool opt4001_volatile_reg(struct device *dev, unsigned int reg)
switch (reg) {
case OPT4001_LIGHT1_MSB:
case OPT4001_LIGHT1_LSB:
+ case OPT4041_LIGHT2_MSB:
+ case OPT4041_LIGHT2_LSB:
return true;
default:
return false;
@@ -447,6 +503,7 @@ static int opt4001_probe(struct i2c_client *client)
static const struct i2c_device_id opt4001_id[] = {
{ .name = "opt4001-sot-5x3", .driver_data = (kernel_ulong_t)&opt4001_sot_5x3_info },
{ .name = "opt4001-picostar", .driver_data = (kernel_ulong_t)&opt4001_picostar_info },
+ { .name = "opt4041-sot-5x3", .driver_data = (kernel_ulong_t)&opt4041_sot_5x3_info },
{ }
};
MODULE_DEVICE_TABLE(i2c, opt4001_id);
@@ -454,6 +511,7 @@ MODULE_DEVICE_TABLE(i2c, opt4001_id);
static const struct of_device_id opt4001_of_match[] = {
{ .compatible = "ti,opt4001-sot-5x3", .data = &opt4001_sot_5x3_info},
{ .compatible = "ti,opt4001-picostar", .data = &opt4001_picostar_info},
+ { .compatible = "ti,opt4041-sot-5x3", .data = &opt4041_sot_5x3_info},
{ }
};
MODULE_DEVICE_TABLE(of, opt4001_of_match);
@@ -469,5 +527,5 @@ static struct i2c_driver opt4001_driver = {
module_i2c_driver(opt4001_driver);
MODULE_AUTHOR("Stefan Windfeldt-Prytz <stefan.windfeldt-prytz@axis.com>");
-MODULE_DESCRIPTION("Texas Instruments opt4001 ambient light sensor driver");
+MODULE_DESCRIPTION("Texas Instruments OPT4001 and compatible Light Sensors");
MODULE_LICENSE("GPL");
--
2.43.0
next prev parent reply other threads:[~2026-10-23 12:30 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-23 12:30 [PATCH v2 0/4] This series adds support for Texas Instruments OPT4041 Ambient light sensor Jesper X Nilsson
2026-10-23 12:30 ` [PATCH v2 1/4] dt-bindings: iio: light: opt4001: add opt4041 Jesper X Nilsson
2026-10-23 12:30 ` [PATCH v2 2/4] iio: light: opt4001: Re-use generic struct s32_fract Jesper X Nilsson
2026-10-23 12:30 ` [PATCH v2 3/4] iio: light: opt4001: refactor driver to prepare to support more devices Jesper X Nilsson
2026-10-23 13:51 ` Andy Shevchenko
2026-10-23 12:30 ` Jesper X Nilsson [this message]
2026-10-23 13:53 ` [PATCH v2 4/4] iio: light: opt4001: add support for opt4041 Andy Shevchenko
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=20261023-opt4041-v2-4-ee320812804c@axis.com \
--to=jesper.x.nilsson@axis.com \
--cc=andy@kernel.org \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=dlechner@baylibre.com \
--cc=jic23@kernel.org \
--cc=kernel@axis.com \
--cc=krzk+dt@kernel.org \
--cc=linux-iio@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=nuno.sa@analog.com \
--cc=robh@kernel.org \
--cc=stefan.windfeldt-prytz@axis.com \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®