[PATCH] video: add ChipWealth CH13726A AMOLED panel driver
Advait Dhamorikar
advaitd at mechasystems.com
Thu Jun 25 15:29:43 CEST 2026
Add support for AMOLED panels based on the ChipWealth CH13726A
MIPI DSI display driver IC.
The driver configures the MIPI DSI interface for 4 data lanes in RGB888
video mode, performs the panel reset sequence, sends the vendor-specific
initialization commands required by the controller, and enables the
panel using the standard MIPI DCS Sleep Out and Display On commands.
This driver is based on an earlier implementation by Pratham Malaviya.
Signed-off-by: Advait Dhamorikar <advaitd at mechasystems.com>
---
drivers/video/Kconfig | 8 ++
drivers/video/Makefile | 1 +
drivers/video/chipwealth-ch13726a.c | 193 ++++++++++++++++++++++++++++
3 files changed, 202 insertions(+)
create mode 100644 drivers/video/chipwealth-ch13726a.c
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index c2acc13139c..7e82778e294 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -533,6 +533,14 @@ config VIDEO_BCM2835
that same resolution (or as near as possible) and 32bpp depth, so
that U-Boot can access it with full colour depth.
+config VIDEO_AMOLED_CHIPWEALTH_CH13726A
+ bool "ChipWealth CH13726A AMOLED panel support"
+ depends on VIDEO
+ select VIDEO_MIPI_DSI
+ help
+ Say Y here if you want to enable support for AMOLED panels
+ based on the ChipWealth CH13726A MIPI DSI display driver IC.
+
config VIDEO_LCD_ENDEAVORU
tristate "Endeavoru 720x1280 DSI video mode panel"
depends on PANEL && BACKLIGHT
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 082b8967982..56df5e1860d 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -55,6 +55,7 @@ obj-$(CONFIG_VIDEO_DW_HDMI) += dw_hdmi.o
obj-$(CONFIG_VIDEO_DW_MIPI_DSI) += dw_mipi_dsi.o
obj-$(CONFIG_VIDEO_EFI) += efi.o
obj-y += imx/
+obj-$(CONFIG_VIDEO_AMOLED_CHIPWEALTH_CH13726A) += chipwealth-ch13726a.o
obj-$(CONFIG_VIDEO_IVYBRIDGE_IGD) += ivybridge_igd.o
obj-$(CONFIG_VIDEO_LCD_PANEL_EDP_4_LANE_1620M_VIA_ANX9804) += anx9804.o
obj-$(CONFIG_VIDEO_LCD_ENDEAVORU) += endeavoru-panel.o
diff --git a/drivers/video/chipwealth-ch13726a.c b/drivers/video/chipwealth-ch13726a.c
new file mode 100644
index 00000000000..e6fef6c8e7f
--- /dev/null
+++ b/drivers/video/chipwealth-ch13726a.c
@@ -0,0 +1,193 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * ChipWealth CH13726A DSI panel driver
+ *
+ * Copyright (C) 2026 Mecha Systems
+ * Author(s):
+ * Advait Dhamorikar <advaitd at mechasystems.com>
+ * Pratham Malaviya <prathamm at mechasystems.com>
+ */
+
+#include <backlight.h>
+#include <dm.h>
+#include <mipi_dsi.h>
+#include <panel.h>
+#include <asm/gpio.h>
+#include <linux/delay.h>
+#include <log.h>
+
+struct ch13726a_panel_priv {
+ struct udevice *reg;
+ struct udevice *backlight;
+ struct gpio_desc reset;
+};
+
+static const struct display_timing default_timing = {
+ .pixelclock.typ = 59832000,
+ .hactive.typ = 1080,
+ .hfront_porch.typ = 12,
+ .hback_porch.typ = 12,
+ .hsync_len.typ = 28,
+ .vactive.typ = 1240,
+ .vfront_porch.typ = 2,
+ .vback_porch.typ = 2,
+ .vsync_len.typ = 2,
+};
+
+static int ch13726a_dcs_write_buf(struct udevice *dev, const void *data,
+ size_t len)
+{
+ struct mipi_dsi_panel_plat *plat = dev_get_plat(dev);
+ int ret;
+
+ ret = mipi_dsi_dcs_write_buffer(plat->device, data, len);
+ if (ret < 0)
+ log_err("failed to write dcs sequence: %d\n", ret);
+
+ return ret;
+}
+
+#define dcs_write_seq(dev, cmd, seq...) \
+({ \
+ const u8 d[] = { cmd, seq }; \
+ \
+ ch13726a_dcs_write_buf(dev, d, ARRAY_SIZE(d)); \
+})
+
+static void ch13726a_reset(struct udevice *dev)
+{
+ struct ch13726a_panel_priv *priv = dev_get_priv(dev);
+
+ dm_gpio_set_value(&priv->reset, true);
+ mdelay(10);
+ dm_gpio_set_value(&priv->reset, false);
+ mdelay(10);
+ dm_gpio_set_value(&priv->reset, true);
+ mdelay(5);
+}
+
+static int ch13726a_set_backlight(struct udevice *dev, int percent)
+{
+ struct mipi_dsi_panel_plat *plat = dev_get_plat(dev);
+ struct mipi_dsi_device *device = plat->device;
+ u8 brightness;
+
+ if (percent < 0)
+ percent = 0;
+ else if (percent > 100)
+ percent = 100;
+
+ brightness = (percent * 255) / 100;
+
+ return mipi_dsi_dcs_set_display_brightness(device, brightness);
+}
+
+static int ch13726a_panel_enable_backlight(struct udevice *dev)
+{
+ struct mipi_dsi_panel_plat *plat = dev_get_plat(dev);
+ struct mipi_dsi_device *device = plat->device;
+ int ret;
+
+ device->lanes = plat->lanes;
+ device->format = plat->format;
+ device->mode_flags = plat->mode_flags;
+
+ ret = mipi_dsi_attach(device);
+ if (ret < 0)
+ return ret;
+
+ ch13726a_reset(dev);
+
+ device->mode_flags |= MIPI_DSI_MODE_LPM;
+
+ ret = dcs_write_seq(dev, 0x53, 0x00);
+ if (ret < 0) {
+ log_debug("%s: Init command failed(%d)\n",
+ __func__, ret);
+ return ret;
+ }
+
+ ret = dcs_write_seq(dev, 0x17, 0x00);
+ if (ret < 0) {
+ log_debug("%s: Init command failed (%d)\n",
+ __func__, ret);
+ return ret;
+ }
+
+ ret = dcs_write_seq(dev, 0x41, 0x00);
+ if (ret < 0) {
+ log_debug("%s: Init command failed (%d)\n",
+ __func__, ret);
+ return ret;
+ }
+
+ ret = mipi_dsi_dcs_exit_sleep_mode(device);
+ if (ret)
+ return ret;
+
+ mdelay(120);
+
+ ret = mipi_dsi_dcs_set_display_on(device);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int ch13726a_panel_get_display_timing(struct udevice *dev,
+ struct display_timing *timings)
+{
+ memcpy(timings, &default_timing, sizeof(*timings));
+ return 0;
+}
+
+static int ch13726a_panel_of_to_plat(struct udevice *dev)
+{
+ struct ch13726a_panel_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ ret = gpio_request_by_name(dev, "reset-gpios", 0,
+ &priv->reset,
+ GPIOD_IS_OUT);
+ if (ret) {
+ log_err("%s: cannot get reset GPIO (%d)\n",
+ __func__, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int ch13726a_panel_probe(struct udevice *dev)
+{
+ struct mipi_dsi_panel_plat *plat = dev_get_plat(dev);
+
+ plat->lanes = 4;
+ plat->format = MIPI_DSI_FMT_RGB888;
+ plat->mode_flags = MIPI_DSI_MODE_VIDEO |
+ MIPI_DSI_MODE_VIDEO_BURST;
+
+ return 0;
+}
+
+static const struct panel_ops ch13726a_panel_ops = {
+ .enable_backlight = ch13726a_panel_enable_backlight,
+ .set_backlight = ch13726a_set_backlight,
+ .get_display_timing = ch13726a_panel_get_display_timing,
+};
+
+static const struct udevice_id ch13726a_panel_ids[] = {
+ { .compatible = "chipwealth,ch13726a" },
+ { }
+};
+
+U_BOOT_DRIVER(ch13726a_panel) = {
+ .name = "ch13726a_panel",
+ .id = UCLASS_PANEL,
+ .of_match = ch13726a_panel_ids,
+ .ops = &ch13726a_panel_ops,
+ .of_to_plat = ch13726a_panel_of_to_plat,
+ .probe = ch13726a_panel_probe,
+ .plat_auto = sizeof(struct mipi_dsi_panel_plat),
+ .priv_auto = sizeof(struct ch13726a_panel_priv),
+};
--
2.43.0
More information about the U-Boot
mailing list