* [PATCH v4 0/2] backlight: Add support for Orient Chip OCP8178
@ 2026-08-26 7:23 Wim de With
2026-08-26 7:23 ` [PATCH v4 1/2] dt-bindings: backlight: Add " Wim de With
2026-08-26 7:23 ` [PATCH v4 2/2] backlight: Add support for " Wim de With
0 siblings, 2 replies; 5+ messages in thread
From: Wim de With @ 2026-08-26 7:23 UTC (permalink / raw)
To: Wim de With, Lee Jones, Daniel Thompson, Jingoo Han, Pavel Machek,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Helge Deller
Cc: dri-devel, linux-leds, devicetree, linux-kernel, linux-fbdev,
Krzysztof Kozlowski
The ClockworkPi uConsole[1] is a modular handheld console manufactured
by Clockwork Tech that runs Linux. It consists of a mainboard which
connects a number of peripherals, such as the screen, batteries and
keyboard. This mainboard hosts a system on a module (SoM), such as the
Raspberry Pi Compute Module as a so-called core to provide the compute
for the device. The device supports different kinds of SoM as cores. The
mainboard is shared between different devices, such as the DevTerm[2].
Currently, the uConsole requires a number of out-of-tree drivers to
support the hardware. In addition, most (if not all) supported SoMs
require vendor kernels. In practice, this means that kernel support for
the device is scattered across various repositories in the form of
patches with dubious quality.
This patch series is the first in an attempt to upstream as many of the
needed drivers as possible. The goal is to support at least the
mainboard and the peripherals of the uConsole in the upstream kernel.
These drivers should find their way downstream to the SoM vendor kernels
eventually.
This series adds the driver for the backlight controller, the Orient
Chip OCP8178. I wrote the driver from scratch using the datasheet, to
avoid any copyright or attribution problems.
[1]: https://www.clockworkpi.com/home-uconsole
[2]: https://www.clockworkpi.com/home-devterm
---
Changes in v4:
No functional changes
- Collect Reviewed-by trailers
- Link to v3: https://patch.msgid.link/20260816-ocp8178-backlight-v3-0-caf95c453c50@dewith.io
Changes in v3:
- Rename enable-gpios to ctrl-gpios
- Remove probe debug message
- Remove onewire debug message
- Link to v2: https://patch.msgid.link/20260812-ocp8178-backlight-v2-0-4ad18b48bef8@dewith.io
Changes in v2:
- Add a note in the commit message that the 1-Wire protocol is not the
one implemented in drivers/w1
- Explicitly reject sleepable GPIO and don't use _cansleep() functions
- Fix bug where interrupts were restored during timing-critical section
- Remove unnecessary logging
- Add missing \n to dev_err_probe message
- Remove linux/mod_devicetable.h include
- Remove struct init padding
- Remove unnecessary backlight_is_blank() check
- Use appropriate delay functions
- Set RFA explicitly and move comment
- Format DT binding YAML
- Link to v1: https://patch.msgid.link/20260806201541.101304-1-wf@dewith.io
---
Wim de With (2):
dt-bindings: backlight: Add Orient Chip OCP8178
backlight: Add support for Orient Chip OCP8178
.../bindings/leds/backlight/ocs,ocp8178.yaml | 47 +++++
MAINTAINERS | 6 +
drivers/video/backlight/Kconfig | 10 +
drivers/video/backlight/Makefile | 1 +
drivers/video/backlight/ocp8178_bl.c | 231 +++++++++++++++++++++
5 files changed, 295 insertions(+)
---
base-commit: 315f4bd234b3b8a3ed3a71fd4c53b110cf373720
change-id: 20260808-ocp8178-backlight-9ead3e930ef3
Best regards,
--
Wim de With <wf@dewith.io>
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v4 1/2] dt-bindings: backlight: Add Orient Chip OCP8178
2026-08-26 7:23 [PATCH v4 0/2] backlight: Add support for Orient Chip OCP8178 Wim de With
@ 2026-08-26 7:23 ` Wim de With
2026-08-26 7:40 ` sashiko-bot
2026-08-26 7:23 ` [PATCH v4 2/2] backlight: Add support for " Wim de With
1 sibling, 1 reply; 5+ messages in thread
From: Wim de With @ 2026-08-26 7:23 UTC (permalink / raw)
To: Wim de With, Lee Jones, Daniel Thompson, Jingoo Han, Pavel Machek,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Helge Deller
Cc: dri-devel, linux-leds, devicetree, linux-kernel, linux-fbdev,
Krzysztof Kozlowski
Add device tree bindings for the Orient Chip OCP8178 LED backlight
driver.
Signed-off-by: Wim de With <wf@dewith.io>
Reviewed-by: Daniel Thompson (RISCstar) <danielt@kernel.org>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
---
.../bindings/leds/backlight/ocs,ocp8178.yaml | 47 ++++++++++++++++++++++
MAINTAINERS | 5 +++
2 files changed, 52 insertions(+)
diff --git a/Documentation/devicetree/bindings/leds/backlight/ocs,ocp8178.yaml b/Documentation/devicetree/bindings/leds/backlight/ocs,ocp8178.yaml
new file mode 100644
index 0000000000000..1cd95aac0d168
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/backlight/ocs,ocp8178.yaml
@@ -0,0 +1,47 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/leds/backlight/ocs,ocp8178.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Orient Chip OCP8178 backlight
+
+maintainers:
+ - Wim de With <wf@dewith.io>
+
+description:
+ The Orient Chip OCP8178 is a white LED backlight driver controlled by a single
+ GPIO line with a vendor-specific onewire protocol.
+
+allOf:
+ - $ref: common.yaml#
+
+properties:
+ compatible:
+ const: ocs,ocp8178
+
+ ctrl-gpios:
+ description: GPIO to use to enable/disable and dim the backlight.
+ maxItems: 1
+
+ default-brightness:
+ maximum: 31
+
+ max-brightness:
+ maximum: 31
+
+required:
+ - compatible
+ - ctrl-gpios
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ backlight {
+ compatible = "ocs,ocp8178";
+ ctrl-gpios = <&gpio2 5 GPIO_ACTIVE_HIGH>;
+ default-brightness = <13>;
+ max-brightness = <31>;
+ };
diff --git a/MAINTAINERS b/MAINTAINERS
index cfee5d47b214d..3ca99d9c32ef1 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -19678,6 +19678,11 @@ F: drivers/mfd/ocelot*
F: drivers/net/dsa/ocelot/ocelot_ext.c
F: include/linux/mfd/ocelot.h
+OCP8178 BACKLIGHT DRIVER
+M: Wim de With <wf@dewith.io>
+S: Maintained
+F: Documentation/devicetree/bindings/leds/backlight/ocs,ocp8178.yaml
+
OCXL (Open Coherent Accelerator Processor Interface OpenCAPI) DRIVER
M: Mahesh J Salgaonkar <mahesh@linux.ibm.com>
R: Andrew Donnellan <andrew+kernel@donnellan.id.au>
--
2.55.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v4 2/2] backlight: Add support for Orient Chip OCP8178
2026-08-26 7:23 [PATCH v4 0/2] backlight: Add support for Orient Chip OCP8178 Wim de With
2026-08-26 7:23 ` [PATCH v4 1/2] dt-bindings: backlight: Add " Wim de With
@ 2026-08-26 7:23 ` Wim de With
2026-08-26 7:44 ` sashiko-bot
1 sibling, 1 reply; 5+ messages in thread
From: Wim de With @ 2026-08-26 7:23 UTC (permalink / raw)
To: Wim de With, Lee Jones, Daniel Thompson, Jingoo Han, Pavel Machek,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Helge Deller
Cc: dri-devel, linux-leds, devicetree, linux-kernel, linux-fbdev
Add a driver for the Orient Chip OCP8178 backlight controller.
The OCP8178 supports either PWM or a vendor-specific onewire protocol
over GPIO. This driver implements the onewire protocol, which enables
setting static brightness levels without requiring a continuous PWM
signal from the host CPU. Note that while the vendor calls the protocol
1-Wire, it is not the 1-Wire protocol from Dallas Semiconductor as
implemented in drivers/w1.
Signed-off-by: Wim de With <wf@dewith.io>
Reviewed-by: Daniel Thompson (RISCstar) <danielt@kernel.org>
---
MAINTAINERS | 1 +
drivers/video/backlight/Kconfig | 10 ++
drivers/video/backlight/Makefile | 1 +
drivers/video/backlight/ocp8178_bl.c | 231 +++++++++++++++++++++++++++++++++++
4 files changed, 243 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 3ca99d9c32ef1..7146e4dea8d78 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -19682,6 +19682,7 @@ OCP8178 BACKLIGHT DRIVER
M: Wim de With <wf@dewith.io>
S: Maintained
F: Documentation/devicetree/bindings/leds/backlight/ocs,ocp8178.yaml
+F: drivers/video/backlight/ocp8178_bl.c
OCXL (Open Coherent Accelerator Processor Interface OpenCAPI) DRIVER
M: Mahesh J Salgaonkar <mahesh@linux.ibm.com>
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index 7aa1c4b21111f..aa845230c5f58 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -226,6 +226,16 @@ config BACKLIGHT_LOCOMO
If you have a Sharp Zaurus SL-5500 (Collie) or SL-5600 (Poodle) say y to
enable the LCD/backlight driver.
+config BACKLIGHT_OCP8178
+ tristate "OCP8178 Backlight Driver"
+ depends on GPIOLIB
+ help
+ If you have an Orient Chip OCP8178, say Y to enable the backlight
+ driver.
+
+ To compile this driver as a module, choose M here: the module will
+ be called ocp8178_bl.
+
config BACKLIGHT_OMAP1
tristate "OMAP1 PWL-based LCD Backlight"
depends on ARCH_OMAP1 || COMPILE_TEST
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index 21c8313cfb121..c4e87b708ae21 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -51,6 +51,7 @@ obj-$(CONFIG_BACKLIGHT_MAX25014) += max25014.o
obj-$(CONFIG_BACKLIGHT_MAX8925) += max8925_bl.o
obj-$(CONFIG_BACKLIGHT_MP3309C) += mp3309c.o
obj-$(CONFIG_BACKLIGHT_MT6370) += mt6370-backlight.o
+obj-$(CONFIG_BACKLIGHT_OCP8178) += ocp8178_bl.o
obj-$(CONFIG_BACKLIGHT_OMAP1) += omap1_bl.o
obj-$(CONFIG_BACKLIGHT_PANDORA) += pandora_bl.o
obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o
diff --git a/drivers/video/backlight/ocp8178_bl.c b/drivers/video/backlight/ocp8178_bl.c
new file mode 100644
index 0000000000000..6c1e8c9451f12
--- /dev/null
+++ b/drivers/video/backlight/ocp8178_bl.c
@@ -0,0 +1,231 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Orient Chip OCP8178 Backlight Driver
+ *
+ * Copyright (C) 2026 Wim de With
+ *
+ * Author: Wim de With <wf@dewith.io>
+ */
+
+#include <linux/backlight.h>
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/gpio/consumer.h>
+#include <linux/irqflags.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
+
+#define OCP8178_MAX_BRIGHTNESS 0x1F /* 5 bits */
+
+#define OCP8178_DEVICE_ADDRESS 0x72
+
+#define OCP8178_DATA_RFA BIT(7)
+#define OCP8178_DATA_ADDR GENMASK(6, 5)
+#define OCP8178_DATA_VALUE GENMASK(4, 0)
+
+#define OCP8178_1W_INIT_MAX_RETRIES 5
+#define OCP8178_1W_INIT_SLEEP_US (50 * 1000)
+
+#define OCP8178_T_OFF_US (3 * 1000) /* datasheet specifies at least 2.5 ms */
+#define OCP8178_1W_T_DELAY_US (100 + 10) /* 10 us as safety factor */
+#define OCP8178_1W_T_DETECT_US (260 + 10) /* 10 us as safety factor */
+#define OCP8178_1W_T_START_US 2
+#define OCP8178_1W_T_EOS_US 2
+#define OCP8178_1W_T_WIN_NS (1000 * 1000)
+
+/*
+ * The datasheet specifies 1.7 Kbps to 160 Kbps.
+ * 1 / (160 Kbps) is about 6.67 us, so using 7 us per bit should be fine.
+ * T_HIGH + T_LOW = 7 us
+ * T_HIGH > 2 * T_LOW for high bits
+ * T_LOW > 2 * T_HIGH for low bits
+ */
+#define OCP8178_1W_HIGH_BIT_T_LOW_US 2
+#define OCP8178_1W_HIGH_BIT_T_HIGH_US 5
+#define OCP8178_1W_LOW_BIT_T_LOW_US 5
+#define OCP8178_1W_LOW_BIT_T_HIGH_US 2
+
+struct ocp8178_bl {
+ struct device *dev;
+ struct gpio_desc *gpiod;
+};
+
+static int ocp8178_bl_enable_onewire(struct ocp8178_bl *ocp8178)
+{
+ u64 start, duration;
+
+ gpiod_set_value(ocp8178->gpiod, 0);
+ fsleep(OCP8178_T_OFF_US);
+
+ start = ktime_get_ns();
+
+ gpiod_set_value(ocp8178->gpiod, 1);
+ udelay(OCP8178_1W_T_DELAY_US);
+ gpiod_set_value(ocp8178->gpiod, 0);
+ udelay(OCP8178_1W_T_DETECT_US);
+ gpiod_set_value(ocp8178->gpiod, 1);
+
+ duration = ktime_get_ns() - start;
+
+ if (duration >= OCP8178_1W_T_WIN_NS) {
+ dev_err(ocp8178->dev,
+ "onewire detection window exceeded (%llu ns)\n",
+ duration);
+ return -EAGAIN;
+ }
+
+ return 0;
+}
+
+static void ocp8178_bl_write_u8(struct ocp8178_bl *ocp8178, u8 value)
+{
+ unsigned long flags;
+
+ gpiod_set_value(ocp8178->gpiod, 1);
+ udelay(OCP8178_1W_T_START_US);
+
+ local_irq_save(flags);
+
+ for (int i = 7; i >= 0; i--) {
+ if ((value >> i) & 1) {
+ gpiod_set_value(ocp8178->gpiod, 0);
+ udelay(OCP8178_1W_HIGH_BIT_T_LOW_US);
+ gpiod_set_value(ocp8178->gpiod, 1);
+ udelay(OCP8178_1W_HIGH_BIT_T_HIGH_US);
+ } else {
+ gpiod_set_value(ocp8178->gpiod, 0);
+ udelay(OCP8178_1W_LOW_BIT_T_LOW_US);
+ gpiod_set_value(ocp8178->gpiod, 1);
+ udelay(OCP8178_1W_LOW_BIT_T_HIGH_US);
+ }
+ }
+
+ gpiod_set_value(ocp8178->gpiod, 0);
+ udelay(OCP8178_1W_T_EOS_US);
+ gpiod_set_value(ocp8178->gpiod, 1);
+
+ local_irq_restore(flags);
+}
+
+static void ocp8178_bl_set_brightness(struct ocp8178_bl *ocp8178, u8 brightness)
+{
+ u8 data = 0;
+
+ /*
+ * We cannot set RFA (request for acknowledge) unless the GPIO pin is
+ * configured as open drain.
+ */
+ data |= FIELD_PREP(OCP8178_DATA_RFA, 0);
+ data |= FIELD_PREP(OCP8178_DATA_ADDR, 0);
+ data |= FIELD_PREP(OCP8178_DATA_VALUE, brightness);
+
+ ocp8178_bl_write_u8(ocp8178, OCP8178_DEVICE_ADDRESS);
+ ocp8178_bl_write_u8(ocp8178, data);
+}
+
+static int ocp8178_bl_update_status(struct backlight_device *bl)
+{
+ struct ocp8178_bl *ocp8178 = bl_get_data(bl);
+ u8 brightness = backlight_get_brightness(bl);
+
+ ocp8178_bl_set_brightness(ocp8178, brightness);
+ return 0;
+}
+
+static const struct backlight_ops ocp8178_bl_ops = {
+ .options = BL_CORE_SUSPENDRESUME,
+ .update_status = ocp8178_bl_update_status,
+};
+
+static int ocp8178_bl_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct backlight_device *bl;
+ struct backlight_properties props;
+ struct ocp8178_bl *ocp8178;
+ u32 max_brightness, brightness;
+ int ret, retries;
+
+ ocp8178 = devm_kzalloc(dev, sizeof(*ocp8178), GFP_KERNEL);
+ if (!ocp8178)
+ return -ENOMEM;
+
+ ocp8178->dev = dev;
+
+ ret = device_property_read_u32(dev, "max-brightness", &max_brightness);
+ if (ret)
+ max_brightness = OCP8178_MAX_BRIGHTNESS;
+ if (max_brightness > OCP8178_MAX_BRIGHTNESS) {
+ dev_warn(dev, "max brightness exceeds hardware limit\n");
+ max_brightness = OCP8178_MAX_BRIGHTNESS;
+ }
+
+ ret = device_property_read_u32(dev, "default-brightness", &brightness);
+ if (ret)
+ brightness = max_brightness;
+ if (brightness > max_brightness) {
+ dev_warn(dev, "default brightness exceeds max brightness\n");
+ brightness = max_brightness;
+ }
+
+ ocp8178->gpiod = devm_gpiod_get(dev, "ctrl", GPIOD_OUT_LOW);
+ if (IS_ERR(ocp8178->gpiod))
+ return dev_err_probe(dev, PTR_ERR(ocp8178->gpiod),
+ "GPIO missing or invalid\n");
+ if (gpiod_cansleep(ocp8178->gpiod))
+ return dev_err_probe(dev, -EINVAL,
+ "sleeping GPIO not supported\n");
+ gpiod_set_consumer_name(ocp8178->gpiod, dev_name(dev));
+
+ for (retries = 0; retries < OCP8178_1W_INIT_MAX_RETRIES; retries++) {
+ ret = ocp8178_bl_enable_onewire(ocp8178);
+ if (!ret)
+ break;
+ if (ret != -EAGAIN)
+ return ret;
+ fsleep(OCP8178_1W_INIT_SLEEP_US);
+ }
+ if (retries >= OCP8178_1W_INIT_MAX_RETRIES)
+ return dev_err_probe(dev, -ETIMEDOUT,
+ "failed to initialize onewire protocol\n");
+
+ props = (typeof(props)){
+ .type = BACKLIGHT_RAW,
+ .brightness = brightness,
+ .max_brightness = max_brightness,
+ .power = BACKLIGHT_POWER_ON,
+ .scale = BACKLIGHT_SCALE_NON_LINEAR,
+ };
+
+ bl = devm_backlight_device_register(dev, dev_name(dev), dev, ocp8178,
+ &ocp8178_bl_ops, &props);
+ if (IS_ERR(bl))
+ return dev_err_probe(dev, PTR_ERR(bl),
+ "failed to register backlight\n");
+
+ platform_set_drvdata(pdev, bl);
+ backlight_update_status(bl);
+
+ return 0;
+}
+
+static const struct of_device_id ocp8178_bl_of_match[] = {
+ { .compatible = "ocs,ocp8178" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, ocp8178_bl_of_match);
+
+static struct platform_driver ocp8178_bl_driver = {
+ .driver = {
+ .name = "ocp8178-bl",
+ .of_match_table = ocp8178_bl_of_match,
+ },
+ .probe = ocp8178_bl_probe,
+};
+module_platform_driver(ocp8178_bl_driver);
+
+MODULE_AUTHOR("Wim de With <wf@dewith.io>");
+MODULE_DESCRIPTION("Orient Chip OCP8178 Backlight Driver");
+MODULE_LICENSE("GPL");
--
2.55.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v4 1/2] dt-bindings: backlight: Add Orient Chip OCP8178
2026-08-26 7:23 ` [PATCH v4 1/2] dt-bindings: backlight: Add " Wim de With
@ 2026-08-26 7:40 ` sashiko-bot
0 siblings, 0 replies; 5+ messages in thread
From: sashiko-bot @ 2026-08-26 7:40 UTC (permalink / raw)
To: Wim de With; +Cc: dri-devel, devicetree, robh, lee, conor+dt, linux-leds
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] Using `additionalProperties: false` with an `allOf` `$ref` breaks property inheritance.
--
commit 76f37f9a56bf914fefbc5653351c8e4714ee18e8
Author: Wim de With <wf@dewith.io>
dt-bindings: backlight: Add Orient Chip OCP8178
Add device tree bindings for the Orient Chip OCP8178 LED backlight
driver.
> diff --git a/Documentation/devicetree/bindings/leds/backlight/ocs,ocp8178.yaml b/Documentation/devicetree/bindings/leds/backlight/ocs,ocp8178.yaml
> new file mode 100644
> index 0000000000000..1cd95aac0d168
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/leds/backlight/ocs,ocp8178.yaml
[ ... ]
> +allOf:
> + - $ref: common.yaml#
> +
> +properties:
> + compatible:
> + const: ocs,ocp8178
[ ... ]
> +required:
> + - compatible
> + - ctrl-gpios
> +
> +additionalProperties: false
[Severity: Medium]
Since this schema includes an allOf reference to common.yaml#, does using
additionalProperties: false break property inheritance? This will reject
standard backlight properties not explicitly listed in the local schema
during device tree validation.
Should this use unevaluatedProperties: false instead?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260826-ocp8178-backlight-v4-0-47d7acce882e@dewith.io?part=1
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v4 2/2] backlight: Add support for Orient Chip OCP8178
2026-08-26 7:23 ` [PATCH v4 2/2] backlight: Add support for " Wim de With
@ 2026-08-26 7:44 ` sashiko-bot
0 siblings, 0 replies; 5+ messages in thread
From: sashiko-bot @ 2026-08-26 7:44 UTC (permalink / raw)
To: Wim de With; +Cc: devicetree, dri-devel, lee, robh, linux-leds, conor+dt
Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:
- [High] Missing 1-wire initialization on system resume leaves the device unresponsive or at maximum brightness.
- [High] Software bitbanging timings are too tight and will likely violate protocol requirements due to execution overhead.
- [High] Calling gpiod_set_value() with hardware interrupts disabled causes a sleeping-in-atomic bug on PREEMPT_RT kernels.
- [Medium] Preemption during onewire initialization can cause silent failure.
- [Low] Using dev_err() for expected, retryable preemption events will spam the kernel log.
--
commit 999030427b1d2e4a9b850939beacde4b60c21042
Author: Wim de With <wf@dewith.io>
backlight: Add support for Orient Chip OCP8178
This patch introduces a new backlight driver for the Orient Chip OCP8178.
It implements a vendor-specific onewire protocol over GPIO to set static
brightness levels without requiring a continuous PWM signal.
> diff --git a/drivers/video/backlight/ocp8178_bl.c b/drivers/video/backlight/ocp8178_bl.c
> new file mode 100644
> index 0000000000000..6c1e8c9451f12
> --- /dev/null
> +++ b/drivers/video/backlight/ocp8178_bl.c
[ ... ]
> +static int ocp8178_bl_enable_onewire(struct ocp8178_bl *ocp8178)
> +{
> + u64 start, duration;
> +
> + gpiod_set_value(ocp8178->gpiod, 0);
> + fsleep(OCP8178_T_OFF_US);
> +
> + start = ktime_get_ns();
> +
> + gpiod_set_value(ocp8178->gpiod, 1);
> + udelay(OCP8178_1W_T_DELAY_US);
> + gpiod_set_value(ocp8178->gpiod, 0);
> + udelay(OCP8178_1W_T_DETECT_US);
[Severity: Medium]
Since this precise timing pulse is generated without preemption or IRQ
protection, could an interrupt stretch the 110us pulse?
If it stretches to 300us, the total duration (300 + 270 = 570us) still passes
the 1ms check below, but the malformed timing causes the hardware to reject
the switch to 1-wire mode, leading to a silent failure.
> + gpiod_set_value(ocp8178->gpiod, 1);
> +
> + duration = ktime_get_ns() - start;
> +
> + if (duration >= OCP8178_1W_T_WIN_NS) {
> + dev_err(ocp8178->dev,
> + "onewire detection window exceeded (%llu ns)\n",
> + duration);
[Severity: Low]
Because initialization runs with interrupts enabled, transient preemption will
cause this window to exceed 1ms and return -EAGAIN for an automatic retry.
Will using dev_err() here cause unnecessary log spam on busy systems?
> + return -EAGAIN;
> + }
> +
> + return 0;
> +}
> +
> +static void ocp8178_bl_write_u8(struct ocp8178_bl *ocp8178, u8 value)
> +{
> + unsigned long flags;
> +
> + gpiod_set_value(ocp8178->gpiod, 1);
> + udelay(OCP8178_1W_T_START_US);
> +
> + local_irq_save(flags);
> +
> + for (int i = 7; i >= 0; i--) {
> + if ((value >> i) & 1) {
> + gpiod_set_value(ocp8178->gpiod, 0);
[Severity: High]
Does calling gpiod_set_value() with hardware interrupts disabled cause a
sleeping-in-atomic bug on PREEMPT_RT kernels?
Memory-mapped GPIO drivers typically use spinlock_t to serialize register
accesses, which becomes a sleepable rt_mutex on PREEMPT_RT. Any userspace
write to the brightness sysfs node will trigger this execution path.
> + udelay(OCP8178_1W_HIGH_BIT_T_LOW_US);
> + gpiod_set_value(ocp8178->gpiod, 1);
> + udelay(OCP8178_1W_HIGH_BIT_T_HIGH_US);
> + } else {
> + gpiod_set_value(ocp8178->gpiod, 0);
> + udelay(OCP8178_1W_LOW_BIT_T_LOW_US);
> + gpiod_set_value(ocp8178->gpiod, 1);
> + udelay(OCP8178_1W_LOW_BIT_T_HIGH_US);
[Severity: High]
Are these software bitbanging timings too tight to satisfy the protocol?
The protocol requires T_LOW > 2 * T_HIGH for a low bit. The driver uses
udelay(2) for T_HIGH and udelay(5) for T_LOW. After udelay(2), the loop logic
evaluates conditions and decrements variables before pulling the line LOW again.
This CPU overhead executes while the line remains HIGH, stretching T_HIGH by
1-2us, making 2 * T_HIGH (~6-8us) strictly greater than T_LOW (5us) and breaking
the requirement.
> + }
> + }
> +
> + gpiod_set_value(ocp8178->gpiod, 0);
> + udelay(OCP8178_1W_T_EOS_US);
> + gpiod_set_value(ocp8178->gpiod, 1);
> +
> + local_irq_restore(flags);
> +}
[ ... ]
> +static const struct backlight_ops ocp8178_bl_ops = {
> + .options = BL_CORE_SUSPENDRESUME,
[Severity: High]
Does using BL_CORE_SUSPENDRESUME leave the device unresponsive after a
system suspend?
If the system is suspended and power is cut to the chip, or the GPIO line
goes low for >2.5ms, the device resets to its default PWM mode. On resume,
the backlight core simply restores the brightness by calling
ocp8178_bl_update_status() without ensuring the hardware is in 1-Wire mode.
Because the driver relies on BL_CORE_SUSPENDRESUME and lacks device PM ops in
ocp8178_bl_driver, it fails to re-transmit the required enable_onewire sequence.
> + .update_status = ocp8178_bl_update_status,
> +};
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260826-ocp8178-backlight-v4-0-47d7acce882e@dewith.io?part=2
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-08-26 7:44 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-26 7:23 [PATCH v4 0/2] backlight: Add support for Orient Chip OCP8178 Wim de With
2026-08-26 7:23 ` [PATCH v4 1/2] dt-bindings: backlight: Add " Wim de With
2026-08-26 7:40 ` sashiko-bot
2026-08-26 7:23 ` [PATCH v4 2/2] backlight: Add support for " Wim de With
2026-08-26 7:44 ` sashiko-bot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox