From: Johannes Schneider <johannes.schneider@leica-geosystems.com>
To: barebox@lists.infradead.org
Cc: thomas.haemmerle@leica-geosystems.com
Subject: [PATCH 5/6] video: add generic panel-lvds driver
Date: Tue, 2 Jun 2026 04:09:51 +0000 [thread overview]
Message-ID: <20260602040953.1060278-6-johannes.schneider@leica-geosystems.com> (raw)
In-Reply-To: <20260602040953.1060278-1-johannes.schneider@leica-geosystems.com>
From: Thomas Haemmerle <thomas.haemmerle@leica-geosystems.com>
Barebox has no driver for "panel-lvds" compatible DT nodes, which are used by
all i.MX8M board display pipelines to describe LVDS panels with a panel-timing
subnode. Without this driver the VPL chain in fsl-ldb terminates before it can
query video modes, and the LCDIF2 framebuffer driver cannot determine the active
display resolution, so no framebuffer is allocated and no splash is shown.
The driver reads one video mode from the panel-timing subnode, enables
an optional power-supply regulator and enable GPIO on VPL_ENABLE, and
controls an optional backlight device. Closely follows the Linux
drivers/gpu/drm/panel/panel-lvds.c behavior.
Assisted-by: Claude:claude-sonnet-4-6
Signed-of-by: Thomas Haemmerle <thomas.haemmerle@leica-geosystems.com>
---
drivers/video/Kconfig | 9 ++
drivers/video/Makefile | 1 +
drivers/video/panel-lvds.c | 175 +++++++++++++++++++++++++++++++++++++
3 files changed, 185 insertions(+)
create mode 100644 drivers/video/panel-lvds.c
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index fbcec6fd67..964c2c8a29 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -204,6 +204,15 @@ config DRIVER_VIDEO_IMX_LCDIF
Supports the "fsl,imx8mp-lcdif" compatible. Creates a simple-framebuffer
device tree node for kernel handoff via DRM_SIMPLEDRM.
+config DRIVER_VIDEO_PANEL_LVDS
+ bool "Generic LVDS panel support"
+ select VIDEO_VPL
+ depends on OFTREE && OFDEVICE
+ help
+ Driver for "panel-lvds" compatible display panels. Reads the video
+ mode from a "panel-timing" subnode and controls the panel power
+ supply regulator.
+
config DRIVER_VIDEO_SIMPLE_PANEL
bool "Simple panel support"
select VIDEO_VPL
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 9957ff5ad2..9d073fdf75 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_VIDEO_VPL) += vpl.o
obj-$(CONFIG_DRIVER_VIDEO_MTL017) += mtl017.o
obj-$(CONFIG_DRIVER_VIDEO_TC358767) += tc358767.o
obj-$(CONFIG_DRIVER_VIDEO_IMX_LCDIF) += imx-lcdif.o
+obj-$(CONFIG_DRIVER_VIDEO_PANEL_LVDS) += panel-lvds.o
obj-$(CONFIG_DRIVER_VIDEO_SIMPLE_PANEL) += simple-panel.o
obj-$(CONFIG_DRIVER_VIDEO_MIPI_DBI) += mipi_dbi.o
obj-$(CONFIG_DRIVER_VIDEO_MIPI_DSI) += mipi_dsi.o
diff --git a/drivers/video/panel-lvds.c b/drivers/video/panel-lvds.c
new file mode 100644
index 0000000000..80d0b105ba
--- /dev/null
+++ b/drivers/video/panel-lvds.c
@@ -0,0 +1,175 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * LVDS panel driver for barebox
+ *
+ * Supports "panel-lvds" compatible panels with a "panel-timing" subnode.
+ *
+ * Based on Linux drivers/gpu/drm/panel/panel-lvds.c
+ * Copyright (C) 2017 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * Copyright Leica Geosystems AG
+ */
+
+#include <common.h>
+#include <init.h>
+#include <driver.h>
+#include <linux/err.h>
+#include <of.h>
+#include <fb.h>
+#include <regulator.h>
+#include <gpio.h>
+#include <of_gpio.h>
+#include <video/vpl.h>
+#include <video/backlight.h>
+
+struct panel_lvds {
+ struct device *dev;
+ struct vpl vpl;
+ struct regulator *power;
+ int enable_gpio;
+ enum of_gpio_flags enable_gpio_flags;
+ struct device_node *backlight_node;
+ struct backlight_device *backlight;
+ struct fb_videomode mode;
+ bool mode_valid;
+};
+
+static int panel_lvds_enable(struct panel_lvds *panel)
+{
+ int ret;
+
+ if (panel->power) {
+ ret = regulator_enable(panel->power);
+ if (ret) {
+ dev_err(panel->dev, "power-supply enable failed: %pe\n",
+ ERR_PTR(ret));
+ return ret;
+ }
+ }
+
+ if (gpio_is_valid(panel->enable_gpio)) {
+ int val = !(panel->enable_gpio_flags & OF_GPIO_ACTIVE_LOW);
+
+ gpio_direction_output(panel->enable_gpio, val);
+ }
+
+ /* Lazily resolve backlight on first enable (may probe after panel) */
+ if (panel->backlight_node && !panel->backlight)
+ panel->backlight = of_backlight_find(panel->backlight_node);
+
+ if (panel->backlight)
+ backlight_set_brightness_default(panel->backlight);
+
+ return 0;
+}
+
+static void panel_lvds_disable(struct panel_lvds *panel)
+{
+ if (panel->backlight)
+ backlight_set_brightness(panel->backlight, 0);
+
+ if (gpio_is_valid(panel->enable_gpio))
+ gpio_direction_output(panel->enable_gpio,
+ !!(panel->enable_gpio_flags & OF_GPIO_ACTIVE_LOW));
+
+ if (panel->power)
+ regulator_disable(panel->power);
+}
+
+static int panel_lvds_ioctl(struct vpl *vpl, unsigned int port,
+ unsigned int cmd, void *ptr)
+{
+ struct panel_lvds *panel = container_of(vpl, struct panel_lvds, vpl);
+ struct display_timings *timings;
+
+ switch (cmd) {
+ case VPL_ENABLE:
+ return panel_lvds_enable(panel);
+
+ case VPL_DISABLE:
+ panel_lvds_disable(panel);
+ return 0;
+
+ case VPL_PREPARE:
+ case VPL_UNPREPARE:
+ return 0;
+
+ case VPL_GET_VIDEOMODES:
+ timings = ptr;
+ if (!panel->mode_valid)
+ return -ENOENT;
+ timings->modes = &panel->mode;
+ timings->num_modes = 1;
+ return 0;
+
+ default:
+ return 0;
+ }
+}
+
+static int panel_lvds_probe(struct device *dev)
+{
+ struct panel_lvds *panel;
+ int ret;
+
+ panel = xzalloc(sizeof(*panel));
+ panel->dev = dev;
+
+ /* Parse panel-timing subnode */
+ ret = of_get_display_timing(dev->of_node, "panel-timing", &panel->mode);
+ if (ret) {
+ dev_err(dev, "failed to parse panel-timing: %d\n", ret);
+ return ret;
+ }
+ panel->mode_valid = true;
+
+ panel->power = regulator_get(dev, "power");
+ if (IS_ERR(panel->power)) {
+ /*
+ * power-supply is optional; if not present continue without it.
+ * This matches the Linux driver behavior.
+ */
+ if (PTR_ERR(panel->power) == -ENODEV)
+ panel->power = NULL;
+ else
+ return dev_errp_probe(dev, panel->power, "power supply\n");
+ }
+
+ panel->enable_gpio = of_get_named_gpio_flags(dev->of_node, "enable-gpios",
+ 0, &panel->enable_gpio_flags);
+ if (gpio_is_valid(panel->enable_gpio)) {
+ int initial = (panel->enable_gpio_flags & OF_GPIO_ACTIVE_LOW) ? 1 : 0;
+
+ ret = gpio_request(panel->enable_gpio, "panel-enable");
+ if (ret)
+ dev_warn(dev, "failed to request enable-gpio: %d\n", ret);
+ else
+ gpio_direction_output(panel->enable_gpio, initial);
+ }
+
+ panel->backlight_node = of_parse_phandle(dev->of_node, "backlight", 0);
+
+ panel->vpl.node = dev->of_node;
+ panel->vpl.ioctl = panel_lvds_ioctl;
+
+ ret = vpl_register(&panel->vpl);
+ if (ret)
+ return ret;
+
+ dev_dbg(dev, "LVDS panel %dx%d registered\n",
+ panel->mode.xres, panel->mode.yres);
+ return 0;
+}
+
+static const struct of_device_id panel_lvds_dt_ids[] = {
+ { .compatible = "panel-lvds" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, panel_lvds_dt_ids);
+
+static struct driver panel_lvds_driver = {
+ .name = "panel-lvds",
+ .probe = panel_lvds_probe,
+ .of_compatible = DRV_OF_COMPAT(panel_lvds_dt_ids),
+};
+device_platform_driver(panel_lvds_driver);
--
2.43.0
next prev parent reply other threads:[~2026-06-02 4:11 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-02 4:09 [PATCH 0/7] video: enable boot splash on i.MX8MP with LVDS panel Johannes Schneider
2026-06-02 4:09 ` [PATCH 1/6] clk: imx8mp: add 700 MHz rate entry for VIDEO_PLL1 Johannes Schneider
2026-06-02 7:04 ` Ahmad Fatoum
2026-06-02 4:09 ` [PATCH 2/6] pmdomain: imx8mp-blk-ctrl: add media blk-ctrl power domain support Johannes Schneider
2026-06-02 7:34 ` Ahmad Fatoum
2026-06-02 4:09 ` [PATCH 3/6] video: backlight-pwm: make power-supply and enable-gpio optional Johannes Schneider
2026-06-02 7:22 ` Ahmad Fatoum
2026-06-02 4:09 ` [PATCH 4/6] video: add i.MX8MP LCDIF2 V8 framebuffer driver Johannes Schneider
2026-06-02 7:16 ` Ahmad Fatoum
2026-06-04 3:34 ` SCHNEIDER Johannes
2026-06-02 4:09 ` Johannes Schneider [this message]
2026-06-02 7:12 ` [PATCH 5/6] video: add generic panel-lvds driver Ahmad Fatoum
2026-06-02 4:09 ` [PATCH 6/6] video: imx-lcdif: drain write-combine buffer before LCDIF DMA reads pixels Johannes Schneider
2026-06-02 8:12 ` Lucas Stach
2026-06-02 9:37 ` Ahmad Fatoum
2026-06-02 12:12 ` Lucas Stach
2026-06-02 15:17 ` Michael Grzeschik
2026-06-02 17:10 ` Michael Grzeschik
2026-06-04 3:42 ` SCHNEIDER Johannes
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=20260602040953.1060278-6-johannes.schneider@leica-geosystems.com \
--to=johannes.schneider@leica-geosystems.com \
--cc=barebox@lists.infradead.org \
--cc=thomas.haemmerle@leica-geosystems.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