mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
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 3/3] iio: light: opt4001: add support for opt4041
Date: Fri, 23 Oct 2026 09:48:15 +0200	[thread overview]
Message-ID: <20261023-opt4041-v1-3-45227f82d05c@axis.com> (raw)
In-Reply-To: <20261023-opt4041-v1-0-45227f82d05c@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
Assisted-by: LLM
Signed-off-by: Jesper X Nilsson <jesper.x.nilsson@axis.com>
---
 drivers/iio/light/Kconfig   |  2 +-
 drivers/iio/light/opt4001.c | 67 ++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 64 insertions(+), 5 deletions(-)

diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig
index 462fff1ddef2..625ebb10ad1b 100644
--- a/drivers/iio/light/Kconfig
+++ b/drivers/iio/light/Kconfig
@@ -508,7 +508,7 @@ config OPT4001
 	select REGMAP_I2C
 	help
 	  If you say Y or M here, you get support for Texas Instruments
-	  OPT4001 Ambient Light Sensor.
+	  OPT4001 and OPT4041 Ambient Light Sensors.
 
 	  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 bf5dc1c8514c..ff142591fcba 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.
+ * Device driver for the Texas Instruments OPT4001 and OPT4041.
  */
 
 #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 {
 	int mul;
@@ -100,6 +105,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 = {
 	.mul = 4375,
 	.div = 10000000,
@@ -118,6 +142,15 @@ 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 = {
+	.mul = 5850,
+	.div = 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 },
@@ -270,10 +303,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];
@@ -340,6 +393,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;
@@ -363,6 +418,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;
@@ -448,6 +505,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);
@@ -455,6 +513,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);
@@ -470,5 +529,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 opt4041 ambient light sensor driver");
 MODULE_LICENSE("GPL");

-- 
2.43.0


  parent reply	other threads:[~2026-10-23  7:48 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-23  7:48 [PATCH 0/3] This series adds support for Texas Instruments OPT4041 Ambient light sensor Jesper X Nilsson
2026-10-23  7:48 ` [PATCH 1/3] dt-bindings: iio: light: opt4001: add opt4041 Jesper X Nilsson
2026-10-23  7:48 ` [PATCH 2/3] iio: light: opt4001: refactor driver to prepare to support more devices Jesper X Nilsson
2026-10-23  9:07   ` Andy Shevchenko
2026-10-23 10:07     ` Jesper X Nilsson
2026-10-23  9:10   ` Joshua Crofts
2026-10-23  9:16     ` Joshua Crofts
2026-10-23 10:22       ` Jesper X Nilsson
2026-10-23  7:48 ` Jesper X Nilsson [this message]
2026-10-23  9:14   ` [PATCH 3/3] iio: light: opt4001: add support for opt4041 Andy Shevchenko
2026-10-23 10:19     ` Jesper X Nilsson
2026-10-23  9:17 ` [PATCH 0/3] This series adds support for Texas Instruments OPT4041 Ambient light sensor Andy Shevchenko
2026-10-23 10:20   ` Jesper X Nilsson

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-v1-3-45227f82d05c@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®