* [PATCH v3 0/4] Add DRM driver for LG LH609QH1 Panel with SiliconWorks SW49410 DDIC
@ 2026-06-15 0:07 Paul Sajna
2026-06-15 0:07 ` [PATCH v3 1/4] drm: panel: Add LG LH609QH1 Panel with SW49410 controller Paul Sajna
` (3 more replies)
0 siblings, 4 replies; 12+ messages in thread
From: Paul Sajna @ 2026-06-15 0:07 UTC (permalink / raw)
To: Neil Armstrong, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Thierry Reding, Sam Ravnborg,
Jessica Zhang, Jessica Zhang
Cc: linux-kernel, dri-devel, devicetree, David Heidelberg,
phone-devel, Amir Dahan, Paul Sajna
This patch series adds a drm panel driver for the LG SW49410 panel found
in the LG G7 ThinQ (codename judyln).
The basic driver skeleton was generated by https://github.com/msm8916-mainline/linux-mdss-dsi-panel-driver-generator
from the vendor device-tree.
There seems to still be some power supply issues, the bottom-left corner
of the screen is dark, and the rest of the screen develops shadow-y
burn-in-like patterns when resumed after being left off for a while.
https://i.imgur.com/oJZSHzE.jpeg
Comments were added explaining magic numbers, MAINTAINERS updated, and devicetree
documentation added
Co-developed-by: Amir Dahan <system64fumo@tuta.io>
Signed-off-by: Amir Dahan <system64fumo@tuta.io>
Signed-off-by: Paul Sajna <sajattack@postmarketos.org>
---
Changes in v3:
- Add power supplies
- Use full panel name including panel and DDIC
- Update email addresses
- Various improvements copied from other similar upstream panels
- Switch back to not using panel-simple due to power supply properties
- Revert incorrect merged panel-simple bindings
- Link to v2: https://lore.kernel.org/r/20250915-judyln-panel-v2-0-01ab2199fea5@postmarketos.org
Changes in v2:
- use "multi" versions of functions
- remove DRM_DISPLAY_DP_HELPER
- change dt-bindings to panel-simple
- Link to v1: https://lore.kernel.org/r/20250910-judyln-panel-v1-0-825c74403bbb@postmarketos.org
---
Amir Dahan (1):
drm: panel: Add LG LH609QH1 Panel with SW49410 controller
Paul Sajna (3):
dt-bindings: display: panel: Add documentation for lg,sw49410-lh609qh1
MAINTAINERS: add Paul Sajna as maintainer for lg,sw49410-lh609qh1
Revert "dt-bindings: display: panel: panel-simple: Add lg,sw49410 compatible"
.../bindings/display/panel/lg,sw49410.yaml | 79 +++
.../bindings/display/panel/panel-simple.yaml | 2 -
MAINTAINERS | 6 +
drivers/gpu/drm/panel/Kconfig | 15 +
drivers/gpu/drm/panel/Makefile | 1 +
drivers/gpu/drm/panel/panel-lg-sw49410.c | 528 +++++++++++++++++++++
6 files changed, 629 insertions(+), 2 deletions(-)
---
base-commit: c9b2552e124828f40d5102b146dc72b506b65de9
change-id: 20250910-judyln-panel-948f177c5c5c
Best regards,
--
Paul Sajna <sajattack@postmarketos.org>
^ permalink raw reply [flat|nested] 12+ messages in thread* [PATCH v3 1/4] drm: panel: Add LG LH609QH1 Panel with SW49410 controller 2026-06-15 0:07 [PATCH v3 0/4] Add DRM driver for LG LH609QH1 Panel with SiliconWorks SW49410 DDIC Paul Sajna @ 2026-06-15 0:07 ` Paul Sajna 2026-06-15 0:18 ` sashiko-bot 2026-06-15 5:40 ` Krzysztof Kozlowski 2026-06-15 0:07 ` [PATCH v3 2/4] dt-bindings: display: panel: Add documentation for lg,sw49410-lh609qh1 Paul Sajna ` (2 subsequent siblings) 3 siblings, 2 replies; 12+ messages in thread From: Paul Sajna @ 2026-06-15 0:07 UTC (permalink / raw) To: Neil Armstrong, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Thierry Reding, Sam Ravnborg, Jessica Zhang, Jessica Zhang Cc: linux-kernel, dri-devel, devicetree, David Heidelberg, phone-devel, Amir Dahan, Paul Sajna From: Amir Dahan <system64fumo@tuta.io> Add panel driver used by LG G7 ThinQ (judyln) Signed-off-by: Amir Dahan <system64fumo@tuta.io> Co-developed-by: Paul Sajna <sajattack@postmarketos.org> Signed-off-by: Paul Sajna <sajattack@postmarketos.org> --- drivers/gpu/drm/panel/Kconfig | 15 + drivers/gpu/drm/panel/Makefile | 1 + drivers/gpu/drm/panel/panel-lg-sw49410.c | 528 +++++++++++++++++++++++++++++++ 3 files changed, 544 insertions(+) diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig index 7450b27622a2..ecf6a45224d3 100644 --- a/drivers/gpu/drm/panel/Kconfig +++ b/drivers/gpu/drm/panel/Kconfig @@ -498,6 +498,21 @@ config DRM_PANEL_LG_SW43408 pixel. It provides a MIPI DSI interface to the host and has a built-in LED backlight. +config DRM_PANEL_LG_SW49410 + tristate "LG SW49410 panel" + depends on OF + depends on DRM_MIPI_DSI + depends on BACKLIGHT_CLASS_DEVICE + select DRM_DISPLAY_DSC_HELPER + select DRM_DISPLAY_HELPER + help + Say Y here if you want to enable support for LG/SiliconWorks SW49410 controller + (found in LG G7 ThinQ). + The LH609QH1 panel has a 1440x3120@60Hz resolution and uses 24 bit RGB per + pixel. It provides a MIPI DSI interface to the host and has a + built-in LED backlight. + To compile this driver as a module, choose M here. + config DRM_PANEL_LXD_M9189A tristate "LXD M9189A MIPI-DSI LCD panel" depends on OF diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile index c2c5cf817116..153970480269 100644 --- a/drivers/gpu/drm/panel/Makefile +++ b/drivers/gpu/drm/panel/Makefile @@ -49,6 +49,7 @@ obj-$(CONFIG_DRM_PANEL_LG_LB035Q02) += panel-lg-lb035q02.o obj-$(CONFIG_DRM_PANEL_LG_LD070WX3) += panel-lg-ld070wx3.o obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o obj-$(CONFIG_DRM_PANEL_LG_SW43408) += panel-lg-sw43408.o +obj-$(CONFIG_DRM_PANEL_LG_SW49410) += panel-lg-sw49410.o obj-$(CONFIG_DRM_PANEL_LXD_M9189A) += panel-lxd-m9189a.o obj-$(CONFIG_DRM_PANEL_MAGNACHIP_D53E6EA8966) += panel-magnachip-d53e6ea8966.o obj-$(CONFIG_DRM_PANEL_MOTOROLA_MOT) += panel-motorola-mot.o diff --git a/drivers/gpu/drm/panel/panel-lg-sw49410.c b/drivers/gpu/drm/panel/panel-lg-sw49410.c new file mode 100644 index 000000000000..02d1b85c3aff --- /dev/null +++ b/drivers/gpu/drm/panel/panel-lg-sw49410.c @@ -0,0 +1,528 @@ +// SPDX-License-Identifier: GPL-2.0+ +// Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree: +// Copyright (c) 2025, The Linux Foundation. All rights reserved. + +#include <linux/backlight.h> +#include <linux/delay.h> +#include <linux/gpio/consumer.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/regulator/consumer.h> + +#include <video/mipi_display.h> + +#include <drm/drm_mipi_dsi.h> +#include <drm/drm_panel.h> +#include <drm/drm_probe_helper.h> +#include <drm/display/drm_dsc.h> +#include <drm/display/drm_dsc_helper.h> + +static const struct regulator_bulk_data sw49410_supplies[] = { + { .supply = "vsp"}, + { .supply = "vsn"}, +}; + + +struct sw49410_panel { + struct drm_panel panel; + struct mipi_dsi_device *dsi; + struct drm_dsc_config dsc; + + struct regulator_bulk_data *supplies; + + struct gpio_desc *reset_gpio; +}; + +static inline +struct sw49410_panel *to_sw49410_panel(struct drm_panel *panel) +{ + return container_of(panel, struct sw49410_panel, panel); +} + +static void sw49410_panel_reset(struct sw49410_panel *ctx) +{ + gpiod_set_value(ctx->reset_gpio, 0); + usleep_range(9000, 10000); + gpiod_set_value(ctx->reset_gpio, 1); + usleep_range(1000, 2000); + gpiod_set_value(ctx->reset_gpio, 0); + usleep_range(9000, 10000); +} + +static int sw49410_panel_program(struct sw49410_panel *ctx) +{ + struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi }; + struct drm_dsc_picture_parameter_set pps; + + + mipi_dsi_dcs_set_tear_on_multi(&dsi_ctx, MIPI_DSI_DCS_TEAR_MODE_VBLANK); + mipi_dsi_dcs_set_page_address_multi(&dsi_ctx, 0x0000, 0x0c2f); + mipi_dsi_dcs_set_display_brightness_multi(&dsi_ctx, 0x00ff); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_WRITE_CONTROL_DISPLAY, + 0x2c); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_SET_CABC_MIN_BRIGHTNESS, + 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_WRITE_POWER_SAVE, 0x81); + + /* Manufacturer protection */ + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, 0xac); + + /* Source Control */ + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb3, + 0x04, 0x04, 0x28, 0x08, 0x5a, 0x12, 0x23, + 0x02); + + /* Gate & Mux Control */ + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb4, + 0x11, 0x04, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xd0, + 0xe4, 0xe4, 0xe4, 0x93, 0x4e, 0x39, 0x0a, + 0x10, 0x18, 0x25, 0x24, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00); + + /* Sync Setup */ + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb5, + 0x2e, 0x0f, 0x10, 0xc0, 0x00, 0x10, 0xc0, + 0x00); + + /* Panel Setting */ + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb6, + 0x03, 0x05, 0x0b, 0xb3, 0x30); + + /* Touch Timing Control */ + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb8, + 0x57, 0x02, 0x90, 0x40, 0x5d, 0xd0, 0x05, + 0x00, 0x00, 0x18, 0x22, 0x04, 0x01, 0x02, + 0x90, 0x40, 0x4c, 0xc0, 0x04, 0x00, 0x00, + 0x18, 0x22, 0x04, 0x01, 0x08, 0x00, 0x3a, + 0x86, 0x83, 0x00); + + /* Touch Source Setting */ + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb9, + 0x64, 0x64, 0x2a, 0x3f, 0xee); + + /* DSC Configuration */ + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xba, + 0x3d, 0x1f, 0x01, 0xff, 0x01, 0x3c, 0x1f, + 0x01, 0xff, 0x01, 0x00); + + /* Low Rate Refresh Setting */ + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xbc, 0x00, 0x00, 0x00, 0x90); + + /* Black Frame Setting */ + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xbd, 0x00, 0x00); + + /* U2 Corner Down */ + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xbf, 0x4f, 0x02); + + /* Internal Oscillator Setting */ + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc0, + 0x00, 0x04, 0x18, 0x07, 0x11, 0x11, 0x3c, + 0x00, 0x0a, 0x0a); + + /* Power Control1 */ + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc1, + 0x01, 0x00, 0xf0, 0xc2, 0xcf, 0x0c); + + /* Power Control2 */ + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc2, + 0xcc, 0x44, 0x44, 0x20, 0x22, 0x26, 0x21, + 0x00); + + /* Power Control3 */ + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc3, + 0x92, 0x11, 0x09, 0x09, 0x11, 0xcc, 0x02, + 0x02, 0xa4, 0xa4, 0x02, 0xa2, 0x38, 0x28, + 0x14, 0x40, 0x38, 0xc0); + + /* Vcom Setting */ + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc4, 0x26, 0x00); + + /* Power Sequence Option Configuration */ + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc9, + 0x05, 0x5d, 0x03, 0x04, 0x00); + + /* Abrupt Power Off Control */ + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xca, 0x9b, 0x10); + + /* LFD Control */ + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xcb, + 0xf3, 0x90, 0x3d, 0x30, 0xcc); + + /* Tail TFT Setting */ + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xcc, + 0x00, 0x40, 0x50, 0x90, 0x41); + + /* U2 Option */ + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xce, 0x00, 0x00); + + /* Gamma */ + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xd0, + 0x12, 0x05, 0x20, 0x1b, 0x2c, 0x28, 0x3f, + 0x3d, 0x4f, 0x4f, 0x66, 0x66, 0x6e, 0x6e, + 0x76, 0x76, 0x80, 0x80, 0x88, 0x88, 0x95, + 0x95, 0x3f, 0x3f, 0xa2, 0xa2, 0x94, 0x94, + 0x8b, 0x8b, 0x81, 0x81, 0x75, 0x75, 0x66, + 0x66, 0x47, 0x47, 0x2d, 0x2d, 0x00, 0x01, + 0x12, 0x05, 0x20, 0x1b, 0x2c, 0x28, 0x3f, + 0x3d, 0x4f, 0x4f, 0x66, 0x66, 0x6e, 0x6e, + 0x76, 0x76, 0x80, 0x80, 0x88, 0x88, 0x95, + 0x95, 0x3f, 0x3f, 0xa2, 0xa2, 0x94, 0x94, + 0x8b, 0x8b, 0x81, 0x81, 0x75, 0x75, 0x66, + 0x66, 0x47, 0x47, 0x2d, 0x2d, 0x00, 0x01, + 0x12, 0x05, 0x20, 0x1b, 0x2c, 0x28, 0x3f, + 0x3d, 0x4f, 0x4f, 0x66, 0x66, 0x6e, 0x6e, + 0x76, 0x76, 0x80, 0x80, 0x88, 0x88, 0x95, + 0x95, 0x3f, 0x3f, 0xa2, 0xa2, 0x94, 0x94, + 0x8b, 0x8b, 0x81, 0x81, 0x75, 0x75, 0x66, + 0x66, 0x47, 0x47, 0x2d, 0x2d, 0x00, 0x01, + 0x12, 0x05, 0x20, 0x1b, 0x2c, 0x28, 0x3f, + 0x3d, 0x4f, 0x4f, 0x66, 0x66, 0x6e, 0x6e, + 0x76, 0x76, 0x80, 0x80, 0x88, 0x88, 0x94, + 0x94, 0x3f, 0x3f, 0xa4, 0xa4, 0x95, 0x95, + 0x8b, 0x8b, 0x81, 0x81, 0x75, 0x75, 0x66, + 0x66, 0x47, 0x47, 0x2d, 0x2d, 0x00, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xd1, + 0x12, 0x05, 0x20, 0x1b, 0x2e, 0x29, 0x41, + 0x3f, 0x52, 0x52, 0x6a, 0x6a, 0x72, 0x72, + 0x7a, 0x7a, 0x84, 0x84, 0x8c, 0x8c, 0x9a, + 0x9a, 0x3f, 0x3f, 0x9b, 0x9b, 0x8d, 0x8d, + 0x84, 0x84, 0x7a, 0x7a, 0x6e, 0x6e, 0x5f, + 0x5f, 0x41, 0x41, 0x2a, 0x2a, 0x00, 0x01, + 0x12, 0x05, 0x20, 0x1b, 0x2e, 0x29, 0x41, + 0x3f, 0x52, 0x52, 0x6a, 0x6a, 0x72, 0x72, + 0x7a, 0x7a, 0x84, 0x84, 0x8c, 0x8c, 0x9a, + 0x9a, 0x3f, 0x3f, 0x9b, 0x9b, 0x8d, 0x8d, + 0x84, 0x84, 0x7a, 0x7a, 0x6e, 0x6e, 0x5f, + 0x5f, 0x41, 0x41, 0x2a, 0x2a, 0x00, 0x01, + 0x12, 0x05, 0x20, 0x1b, 0x2e, 0x29, 0x41, + 0x3f, 0x52, 0x52, 0x6a, 0x6a, 0x72, 0x72, + 0x7a, 0x7a, 0x84, 0x84, 0x8c, 0x8c, 0x9a, + 0x9a, 0x3f, 0x3f, 0x9b, 0x9b, 0x8d, 0x8d, + 0x84, 0x84, 0x7a, 0x7a, 0x6e, 0x6e, 0x5f, + 0x5f, 0x41, 0x41, 0x2a, 0x2a, 0x00, 0x01, + 0x12, 0x05, 0x20, 0x1b, 0x2e, 0x29, 0x41, + 0x3f, 0x52, 0x52, 0x6a, 0x6a, 0x72, 0x72, + 0x7a, 0x7a, 0x84, 0x84, 0x8c, 0x8c, 0x9a, + 0x9a, 0x3f, 0x3f, 0x9b, 0x9b, 0x8d, 0x8d, + 0x84, 0x84, 0x7a, 0x7a, 0x6e, 0x6e, 0x5f, + 0x5f, 0x41, 0x41, 0x2a, 0x2a, 0x00, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xd2, + 0x12, 0x05, 0x20, 0x1b, 0x2f, 0x2a, 0x43, + 0x41, 0x55, 0x55, 0x6e, 0x6e, 0x76, 0x76, + 0x7e, 0x7e, 0x88, 0x88, 0x90, 0x90, 0x9f, + 0x9f, 0x3f, 0x3f, 0x95, 0x95, 0x86, 0x86, + 0x7d, 0x7d, 0x74, 0x74, 0x68, 0x68, 0x59, + 0x59, 0x3c, 0x3c, 0x26, 0x26, 0x00, 0x01, + 0x12, 0x05, 0x20, 0x1b, 0x2f, 0x2a, 0x43, + 0x41, 0x55, 0x55, 0x6e, 0x6e, 0x76, 0x76, + 0x7e, 0x7e, 0x88, 0x88, 0x90, 0x90, 0x9f, + 0x9f, 0x3f, 0x3f, 0x95, 0x95, 0x86, 0x86, + 0x7d, 0x7d, 0x74, 0x74, 0x68, 0x68, 0x59, + 0x59, 0x3c, 0x3c, 0x26, 0x26, 0x00, 0x01, + 0x12, 0x05, 0x20, 0x1b, 0x2f, 0x2a, 0x43, + 0x41, 0x55, 0x55, 0x6e, 0x6e, 0x76, 0x76, + 0x7e, 0x7e, 0x88, 0x88, 0x90, 0x90, 0x9f, + 0x9f, 0x3f, 0x3f, 0x95, 0x95, 0x86, 0x86, + 0x7d, 0x7d, 0x74, 0x74, 0x68, 0x68, 0x59, + 0x59, 0x3c, 0x3c, 0x26, 0x26, 0x00, 0x01, + 0x12, 0x05, 0x20, 0x1b, 0x2f, 0x2a, 0x43, + 0x41, 0x55, 0x55, 0x6e, 0x6e, 0x76, 0x76, + 0x7e, 0x7e, 0x88, 0x88, 0x90, 0x90, 0x9f, + 0x9f, 0x3f, 0x3f, 0x95, 0x95, 0x86, 0x86, + 0x7d, 0x7d, 0x74, 0x74, 0x68, 0x68, 0x59, + 0x59, 0x3c, 0x3c, 0x26, 0x26, 0x00, 0x01); + + /* MPLUS Control */ + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xd3, 0x12, 0x01, 0x00, 0x00); + + /* MPLUS Setting */ + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xd4, + 0xdc, 0x5f, 0x9c, 0xbe, 0x39, 0x39, 0x39, + 0x47, 0x48, 0x48, 0x48, 0x3a, 0x00, 0x03, + 0x6d, 0x80, 0x00, 0x00, 0x8c, 0x66, 0x00, + 0x00, 0x8c, 0x66, 0x00, 0x00, 0x8c, 0x66, + 0x00, 0x0a, 0x48, 0x80, 0x00, 0x0a, 0x48, + 0x80, 0x00, 0x0a, 0x48, 0x80, 0x00, 0x0a, + 0x48, 0x80, 0x20, 0x0a, 0x14, 0x0a, 0x18, + 0x00, 0x1c, 0xcc, 0x23, 0x9e, 0x23, 0x9e, + 0x01, 0x01, 0x01, 0x01, 0x04, 0x04, 0x04, + 0x04, 0x01, 0x00, 0x02, 0x80, 0x00, 0x10, + 0x00, 0x10, 0x00, 0x10, 0x13, 0x9e, 0x13, + 0x9e, 0x13, 0x9e, 0x13, 0x9e, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x23, + 0x9e, 0xff, 0xff, 0x13, 0x33, 0x18, 0x00, + 0x16, 0x66, 0x10, 0x00, 0xff, 0x01, 0x00, + 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, + 0x00, 0x06, 0x00, 0x07, 0x00, 0x08, 0x00, + 0x09, 0x00, 0x0a, 0x00, 0x0b, 0x00, 0x0c, + 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, + 0x1b, 0x25, 0xdc, 0x18, 0x00, 0x20, 0x00, + 0x1c, 0xe1, 0x00, 0xff, 0xe0, 0xc8, 0xc8, + 0x41, 0x8f); + + /* Notch Up Gradation */ + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xad, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x20, 0x40, 0x60, 0x90, 0xc0, + 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff); + + /* Notch Down Gradation */ + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xae, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x20, 0x40, 0x60, 0x90, 0xc0, + 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff); + + /* GIP Setting */ + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe5, + 0x0b, 0x0a, 0x0c, 0x00, 0x02, 0x04, 0x06, + 0x08, 0x0f, 0x1b, 0x02, 0x1a, 0x1a, 0x0b, + 0x0a, 0x0c, 0x01, 0x03, 0x05, 0x07, 0x09, + 0x10, 0x1b, 0x03, 0x1a, 0x1a); + + /* Mux Setting */ + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe6, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, + 0x17, 0x18); + + /* Test1 */ + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xed, + 0x21, 0x49, 0x00, 0x00, 0x00, 0x00); + + /* BLU Control */ + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_WRITE_POWER_SAVE, 0x81); + + /* Sharpness */ + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf3, + 0x00, 0x01, 0x00, 0x0d, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf4, + 0x00, 0x00, 0x40, 0x83, 0xc5, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfb, + 0x20, 0x40, 0x60, 0x80, 0xa0, 0xc0, 0xe0, + 0x13, 0x18, 0x18, 0x18, 0x16, 0x0d, 0x0d, + 0x00, 0xc7, 0xcf, 0xd8, 0xe1, 0xea, 0xf3, + 0xf9, 0xff); + + /* Gamma Correction */ + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf5, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf6, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf7, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf8, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00); + + /* BLU PWM Control */ + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfc, + 0x13, 0x70, 0xd0, 0x26, 0x30, 0x7c, 0x02, + 0xff, 0x12, 0x22, 0x22, 0x10, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_ENTER_NORMAL_MODE); + mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 135); + + /* Black frame setting */ + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xbd, 0x01, 0x05); + + mipi_dsi_dcs_set_display_on_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 50); + + ctx->dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; + + drm_dsc_pps_payload_pack(&pps, &ctx->dsc); + + ctx->dsi->mode_flags |= MIPI_DSI_MODE_LPM; + + mipi_dsi_picture_parameter_set_multi(&dsi_ctx, &pps); + + mipi_dsi_compression_mode_ext_multi(&dsi_ctx, true, MIPI_DSI_COMPRESSION_DSC, 1); + + return dsi_ctx.accum_err; +} + +static int sw49410_panel_disable(struct drm_panel *panel) +{ + struct sw49410_panel *ctx = to_sw49410_panel(panel); + struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi }; + + ctx->dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; + + mipi_dsi_dcs_set_display_off_multi(&dsi_ctx); + mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 128); + + return dsi_ctx.accum_err; +} + +static int sw49410_panel_prepare(struct drm_panel *panel) +{ + struct sw49410_panel *ctx = to_sw49410_panel(panel); + int ret; + + ret = regulator_bulk_enable(ARRAY_SIZE(sw49410_supplies), ctx->supplies); + if (ret < 0) + return ret; + + usleep_range(5000, 6000); + + sw49410_panel_reset(ctx); + + ret = sw49410_panel_program(ctx); + if (ret) + goto poweroff; + + return 0; + +poweroff: + gpiod_set_value(ctx->reset_gpio, 1); + regulator_bulk_disable(ARRAY_SIZE(sw49410_supplies), ctx->supplies); + return ret; +} + +static int sw49410_panel_unprepare(struct drm_panel *panel) +{ + struct sw49410_panel *ctx = to_sw49410_panel(panel); + + gpiod_set_value(ctx->reset_gpio, 1); + struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi }; + + mipi_dsi_dcs_set_display_off_multi(&dsi_ctx); + mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 100); + + gpiod_set_value(ctx->reset_gpio, 1); + + regulator_bulk_disable(ARRAY_SIZE(sw49410_supplies), ctx->supplies); + + return dsi_ctx.accum_err; +} + +static const struct drm_display_mode sw49410_panel_mode = { + .clock = (1440 + 168 + 4 + 84) * (3120 + 2 + 18 + 18) * 60 / 1000, + .hdisplay = 1440, + .hsync_start = 1440 + 168, + .hsync_end = 1440 + 168 + 4, + .htotal = 1440 + 168 + 4 + 84, + .vdisplay = 3120, + .vsync_start = 3120 + 2, + .vsync_end = 3120 + 2 + 18, + .vtotal = 3120 + 2 + 18 + 18, + .width_mm = 65, + .height_mm = 140, + .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, +}; + +static int sw49410_panel_get_modes(struct drm_panel *panel, struct drm_connector *connector) +{ + return drm_connector_helper_get_modes_fixed(connector, &sw49410_panel_mode); +} + +static const struct drm_panel_funcs sw49410_panel_funcs = { + .disable = sw49410_panel_disable, + .prepare = sw49410_panel_prepare, + .unprepare = sw49410_panel_unprepare, + .get_modes = sw49410_panel_get_modes, +}; + +static int sw49410_panel_probe(struct mipi_dsi_device *dsi) +{ + struct device *dev = &dsi->dev; + struct sw49410_panel *ctx; + int ret; + + ctx = devm_drm_panel_alloc(&dsi->dev, __typeof(*ctx), panel, + &sw49410_panel_funcs, DRM_MODE_CONNECTOR_DSI); + + if (IS_ERR(ctx)) + return PTR_ERR(ctx); + + ret = devm_regulator_bulk_get_const(dev, ARRAY_SIZE(sw49410_supplies), + sw49410_supplies, + &ctx->supplies + ); + + if (ret < 0) + return dev_err_probe(dev, ret, "Failed to get regulators\n"); + + ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(ctx->reset_gpio)) + return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio), + "Failed to get reset-gpios\n"); + + ctx->dsi = dsi; + mipi_dsi_set_drvdata(dsi, ctx); + + dsi->lanes = 4; + dsi->format = MIPI_DSI_FMT_RGB888; + dsi->mode_flags = MIPI_DSI_MODE_VIDEO_BURST | + MIPI_DSI_CLOCK_NON_CONTINUOUS; + + ctx->panel.prepare_prev_first = true; + + ret = drm_panel_of_backlight(&ctx->panel); + if (ret) + return dev_err_probe(dev, ret, "Failed to get backlight\n"); + + drm_panel_add(&ctx->panel); + + /* This panel only supports DSC; unconditionally enable it */ + dsi->dsc = &ctx->dsc; + + ctx->dsc.dsc_version_major = 1; + ctx->dsc.dsc_version_minor = 1; + + ctx->dsc.slice_height = 60; + ctx->dsc.slice_width = 720; + + WARN_ON(1440 % ctx->dsc.slice_width); + ctx->dsc.slice_count = 1440 / ctx->dsc.slice_width; + ctx->dsc.bits_per_component = 8; + ctx->dsc.bits_per_pixel = 8 << 4; /* 4 fractional bits */ + ctx->dsc.block_pred_enable = true; + + return mipi_dsi_attach(dsi); +} + +static void sw49410_panel_remove(struct mipi_dsi_device *dsi) +{ + struct sw49410_panel *ctx = mipi_dsi_get_drvdata(dsi); + int ret; + + ret = mipi_dsi_detach(dsi); + if (ret < 0) + dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret); + + drm_panel_remove(&ctx->panel); +} + +static const struct of_device_id sw49410_of_match[] = { + { .compatible = "lg,sw49410" }, + { .compatible = "lg,sw49410-lh609qh1" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, sw49410_of_match); + +static struct mipi_dsi_driver sw49410_panel_driver = { + .driver = { + .name = "panel-lg-sw49410", + .of_match_table = sw49410_of_match, + }, + .probe = sw49410_panel_probe, + .remove = sw49410_panel_remove, +}; +module_mipi_dsi_driver(sw49410_panel_driver); + +MODULE_AUTHOR("Amir Dahan <system64fumo@tuta.io>"); +MODULE_DESCRIPTION("DRM driver for LG DSI Panel with SW49410 controller"); +MODULE_LICENSE("GPL"); -- 2.54.0 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH v3 1/4] drm: panel: Add LG LH609QH1 Panel with SW49410 controller 2026-06-15 0:07 ` [PATCH v3 1/4] drm: panel: Add LG LH609QH1 Panel with SW49410 controller Paul Sajna @ 2026-06-15 0:18 ` sashiko-bot 2026-06-15 5:40 ` Krzysztof Kozlowski 1 sibling, 0 replies; 12+ messages in thread From: sashiko-bot @ 2026-06-15 0:18 UTC (permalink / raw) To: Paul Sajna; +Cc: conor+dt, dri-devel, robh, devicetree Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider: - [High] Missing `drm_panel_remove()` in the `mipi_dsi_attach()` error path causes a global list corruption and Use-After-Free. - [High] DSI commands are sent while the panel is held in reset in `sw49410_panel_unprepare()`. - [Medium] Misplaced `MIPI_DSI_MODE_LPM` flag manipulation around a software memory packing function. - [Medium] The panel is published to the system before its DSC configuration is fully initialized. -- commit 1a6b069af275d9965692f4acaa02ebd1a8517da9 Author: Amir Dahan <system64fumo@tuta.io> Subject: drm: panel: Add LG LH609QH1 Panel with SW49410 controller This commit adds a new panel driver for the LG SW49410 controller used in the LG G7 ThinQ. It configures the panel, sets up the DSI commands, and initializes the DSC parameters. > diff --git a/drivers/gpu/drm/panel/panel-lg-sw49410.c b/drivers/gpu/drm/panel/panel-lg-sw49410.c > new file mode 100644 > --- /dev/null > +++ b/drivers/gpu/drm/panel/panel-lg-sw49410.c [ ... ] > +static int sw49410_panel_program(struct sw49410_panel *ctx) > +{ [ ... ] > + ctx->dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; > + > + drm_dsc_pps_payload_pack(&pps, &ctx->dsc); > + > + ctx->dsi->mode_flags |= MIPI_DSI_MODE_LPM; > + > + mipi_dsi_picture_parameter_set_multi(&dsi_ctx, &pps); [Severity: Medium] Does this code incorrectly clear and restore the MIPI_DSI_MODE_LPM flag? The drm_dsc_pps_payload_pack() function merely formats a local structure in memory and performs no hardware DSI transactions, so manipulating DSI hardware transmission flags around it seems unnecessary. By restoring the flag immediately after packing, does it cause the subsequent mipi_dsi_picture_parameter_set_multi() call to execute in Low Power Mode rather than the intended High Speed mode? [ ... ] > +static int sw49410_panel_unprepare(struct drm_panel *panel) > +{ > + struct sw49410_panel *ctx = to_sw49410_panel(panel); > + > + gpiod_set_value(ctx->reset_gpio, 1); > + struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi }; > + > + mipi_dsi_dcs_set_display_off_multi(&dsi_ctx); > + mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); [Severity: High] Is it intentional to assert the reset GPIO before sending the sleep commands? Because the display controller is held in hardware reset, it cannot receive or process the display off and sleep commands, which could cause the DSI host's transmissions to fail or time out. Looking further down in this function, the reset GPIO is asserted a second time, which suggests this first call might be misplaced. [ ... ] > +static int sw49410_panel_probe(struct mipi_dsi_device *dsi) > +{ [ ... ] > + drm_panel_add(&ctx->panel); > + > + /* This panel only supports DSC; unconditionally enable it */ > + dsi->dsc = &ctx->dsc; > + > + ctx->dsc.dsc_version_major = 1; > + ctx->dsc.dsc_version_minor = 1; [Severity: Medium] Could this cause a race condition where a concurrently probing display driver reads uninitialized DSC settings? Since drm_panel_add() makes the panel visible globally, another driver could find it before the DSC parameters like slice_width and bits_per_component are fully populated. Should drm_panel_add() be called as the final step of initialization? [ ... ] > + ctx->dsc.slice_count = 1440 / ctx->dsc.slice_width; > + ctx->dsc.bits_per_component = 8; > + ctx->dsc.bits_per_pixel = 8 << 4; /* 4 fractional bits */ > + ctx->dsc.block_pred_enable = true; > + > + return mipi_dsi_attach(dsi); > +} [Severity: High] Does returning the error from mipi_dsi_attach() without calling drm_panel_remove() leave a dangling pointer in the global panel list? If mipi_dsi_attach() fails, the probe function returns the error directly. Because the panel context is allocated via devm_drm_panel_alloc(), it will be automatically freed by the driver core. However, since drm_panel_add() was already called, this freed memory would remain linked in the global DRM panel list, leading to a use-after-free the next time the list is traversed. -- Sashiko AI review · https://sashiko.dev/#/patchset/20260614-judyln-panel-v3-0-07f4134441bd@postmarketos.org?part=1 ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v3 1/4] drm: panel: Add LG LH609QH1 Panel with SW49410 controller 2026-06-15 0:07 ` [PATCH v3 1/4] drm: panel: Add LG LH609QH1 Panel with SW49410 controller Paul Sajna 2026-06-15 0:18 ` sashiko-bot @ 2026-06-15 5:40 ` Krzysztof Kozlowski 1 sibling, 0 replies; 12+ messages in thread From: Krzysztof Kozlowski @ 2026-06-15 5:40 UTC (permalink / raw) To: Paul Sajna Cc: Neil Armstrong, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Thierry Reding, Sam Ravnborg, Jessica Zhang, linux-kernel, dri-devel, devicetree, David Heidelberg, phone-devel, Amir Dahan On Sun, Jun 14, 2026 at 05:07:58PM -0700, Paul Sajna wrote: > From: Amir Dahan <system64fumo@tuta.io> > > Add panel driver used by LG G7 ThinQ (judyln) > > Signed-off-by: Amir Dahan <system64fumo@tuta.io> > Co-developed-by: Paul Sajna <sajattack@postmarketos.org> > Signed-off-by: Paul Sajna <sajattack@postmarketos.org> > --- Please organize the patch documenting the compatible (DT bindings) before the patch using that compatible. See also: https://elixir.bootlin.com/linux/v6.14-rc6/source/Documentation/devicetree/bindings/submitting-patches.rst#L46 Best regards, Krzysztof ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v3 2/4] dt-bindings: display: panel: Add documentation for lg,sw49410-lh609qh1 2026-06-15 0:07 [PATCH v3 0/4] Add DRM driver for LG LH609QH1 Panel with SiliconWorks SW49410 DDIC Paul Sajna 2026-06-15 0:07 ` [PATCH v3 1/4] drm: panel: Add LG LH609QH1 Panel with SW49410 controller Paul Sajna @ 2026-06-15 0:07 ` Paul Sajna 2026-06-15 0:17 ` sashiko-bot ` (2 more replies) 2026-06-15 0:08 ` [PATCH v3 3/4] MAINTAINERS: add Paul Sajna as maintainer " Paul Sajna 2026-06-15 0:08 ` [PATCH v3 4/4] Revert "dt-bindings: display: panel: panel-simple: Add lg,sw49410 compatible" Paul Sajna 3 siblings, 3 replies; 12+ messages in thread From: Paul Sajna @ 2026-06-15 0:07 UTC (permalink / raw) To: Neil Armstrong, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Thierry Reding, Sam Ravnborg, Jessica Zhang, Jessica Zhang Cc: linux-kernel, dri-devel, devicetree, David Heidelberg, phone-devel, Amir Dahan, Paul Sajna Document how to use lg,sw49410-lh609qh1 in a devicetree Signed-off-by: Paul Sajna <sajattack@postmarketos.org> --- .../bindings/display/panel/lg,sw49410.yaml | 79 ++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/Documentation/devicetree/bindings/display/panel/lg,sw49410.yaml b/Documentation/devicetree/bindings/display/panel/lg,sw49410.yaml new file mode 100644 index 000000000000..4c4bf4d89353 --- /dev/null +++ b/Documentation/devicetree/bindings/display/panel/lg,sw49410.yaml @@ -0,0 +1,79 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/panel/lg,sw49410.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: LG LH609QH1 MIPI-DSI panel with SW49410 controller + +maintainers: + - Paul Sajna <sajattack@postmarketos.org> + +description: + LG LH609QH1 6.1" 1440x3120 MIPI DSI panel with SW49410 controller found in LG G7 ThinQ smartphone. + +allOf: + - $ref: panel-common.yaml# + +properties: + compatible: + items: + - const: lg,sw49410 + - const: lg,sw49410-lh609qh1 + + reg: + maxItems: 1 + + backlight: + description: Backlight device reference + + reset-gpios: + description: Reset pin reference + + vsp-supply: + description: Positive voltage supply + + vsn-supply: + description: Negative voltage supply + +required: + - compatible + - reg + - reset-gpios + - port + - vsp-supply + - vsn-supply + +unevaluatedProperties: false + +examples: + - | + #include <dt-bindings/gpio/gpio.h> + + dsi { + #address-cells = <1>; + #size-cells = <0>; + + panel@0 { + reg = <0>; + compatible = "lg,sw49410-lh609qh1"; + + backlight = <&pmi8998_wled>; + reset-gpios = <&tlmm 6 GPIO_ACTIVE_LOW>; + width-mm = <65>; + height-mm = <140>; + + vsp-supply = <&lab>; + vsn-supply = <&ibb>; + + pinctrl-0 = <&sde_dsi_active &sde_te_active_sleep>; + pinctrl-1 = <&sde_dsi_sleep &sde_te_active_sleep>; + pinctrl-names = "default", "sleep"; + + port { + panel_in: endpoint { + remote-endpoint = <&mdss_dsi0_out>; + }; + }; + }; + }; -- 2.54.0 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH v3 2/4] dt-bindings: display: panel: Add documentation for lg,sw49410-lh609qh1 2026-06-15 0:07 ` [PATCH v3 2/4] dt-bindings: display: panel: Add documentation for lg,sw49410-lh609qh1 Paul Sajna @ 2026-06-15 0:17 ` sashiko-bot 2026-06-15 5:38 ` Krzysztof Kozlowski 2026-06-15 5:39 ` Krzysztof Kozlowski 2 siblings, 0 replies; 12+ messages in thread From: sashiko-bot @ 2026-06-15 0:17 UTC (permalink / raw) To: Paul Sajna; +Cc: dri-devel, devicetree, robh, conor+dt Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider: - [High] Sending DSI commands in `unprepare` after asserting the reset GPIO will cause DSI transmission timeouts. - [High] The `MIPI_DSI_MODE_LPM` flag toggle for the PPS transfer is wrapped around the wrong function, rendering it ineffective. - [Medium] The `compatible` property definition enforces an incorrect generic-first string order and mismatches the device tree example, causing validation to fail. -- commit faf055f392f23751b6b923b1d2e80556b912da18 Author: Paul Sajna <sajattack@postmarketos.org> dt-bindings: display: panel: Add documentation for lg,sw49410-lh609qh1 This commit documents the bindings for the LG LH609QH1 MIPI DSI panel. It also introduces the DRM panel driver for the SW49410 controller found in the LG G7 ThinQ smartphone. > diff --git a/Documentation/devicetree/bindings/display/panel/lg,sw49410.yaml b/Documentation/devicetree/bindings/display/panel/lg,sw49410.yaml > new file mode 100644 > index 0000000000000..4c4bf4d89353f > --- /dev/null > +++ b/Documentation/devicetree/bindings/display/panel/lg,sw49410.yaml > @@ -0,0 +1,79 @@ [ ... ] > +properties: > + compatible: > + items: > + - const: lg,sw49410 > + - const: lg,sw49410-lh609qh1 [Severity: Medium] Does the compatible array enforce a generic-to-specific order? Device tree standard typically dictates specific-to-generic ordering. Additionally, since the device tree example further down only provides a single string: compatible = "lg,sw49410-lh609qh1"; Will this single-string example fail validation against the two-item schema constraint defined here? > + > + reg: [ ... ] > diff --git a/drivers/gpu/drm/panel/panel-lg-sw49410.c b/drivers/gpu/drm/panel/panel-lg-sw49410.c > new file mode 100644 > index 0000000000000..02d1b85c3affb > --- /dev/null > +++ b/drivers/gpu/drm/panel/panel-lg-sw49410.c > @@ -0,0 +1,528 @@ [ ... ] > +static int sw49410_panel_program(struct sw49410_panel *ctx) > +{ > + struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi }; > + struct drm_dsc_picture_parameter_set pps; [ ... ] > + ctx->dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; > + > + drm_dsc_pps_payload_pack(&pps, &ctx->dsc); > + > + ctx->dsi->mode_flags |= MIPI_DSI_MODE_LPM; > + > + mipi_dsi_picture_parameter_set_multi(&dsi_ctx, &pps); [Severity: High] Are the MIPI_DSI_MODE_LPM flags being toggled around the right function? This code wraps the local memory packing function drm_dsc_pps_payload_pack() instead of the actual transmission function mipi_dsi_picture_parameter_set_multi(). Does this mean the PPS command is still incorrectly sent in low-power mode? > + > + mipi_dsi_compression_mode_ext_multi(&dsi_ctx, true, MIPI_DSI_COMPRESSION_DSC, 1); [ ... ] > +static int sw49410_panel_unprepare(struct drm_panel *panel) > +{ > + struct sw49410_panel *ctx = to_sw49410_panel(panel); > + > + gpiod_set_value(ctx->reset_gpio, 1); > + struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi }; > + > + mipi_dsi_dcs_set_display_off_multi(&dsi_ctx); > + mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); [Severity: High] Could asserting the reset GPIO before sending DSI commands lead to transmission timeouts? Because the panel is already put into reset by gpiod_set_value(..., 1), it seems like it won't be able to acknowledge the display_off and enter_sleep_mode commands sent immediately after. > + mipi_dsi_msleep(&dsi_ctx, 100); -- Sashiko AI review · https://sashiko.dev/#/patchset/20260614-judyln-panel-v3-0-07f4134441bd@postmarketos.org?part=2 ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v3 2/4] dt-bindings: display: panel: Add documentation for lg,sw49410-lh609qh1 2026-06-15 0:07 ` [PATCH v3 2/4] dt-bindings: display: panel: Add documentation for lg,sw49410-lh609qh1 Paul Sajna 2026-06-15 0:17 ` sashiko-bot @ 2026-06-15 5:38 ` Krzysztof Kozlowski 2026-06-15 5:39 ` Krzysztof Kozlowski 2 siblings, 0 replies; 12+ messages in thread From: Krzysztof Kozlowski @ 2026-06-15 5:38 UTC (permalink / raw) To: Paul Sajna Cc: Neil Armstrong, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Thierry Reding, Sam Ravnborg, Jessica Zhang, linux-kernel, dri-devel, devicetree, David Heidelberg, phone-devel, Amir Dahan On Sun, Jun 14, 2026 at 05:07:59PM -0700, Paul Sajna wrote: > Document how to use lg,sw49410-lh609qh1 in a devicetree "Add Foo bar MIPI DSI panel, which suppors somehing something resolution etc." You describe hardware. > > Signed-off-by: Paul Sajna <sajattack@postmarketos.org> > --- > .../bindings/display/panel/lg,sw49410.yaml | 79 ++++++++++++++++++++++ > 1 file changed, 79 insertions(+) > A nit, subject: drop second/last, redundant "documentation for". The "dt-bindings" prefix is already stating that this is documentation. See also: https://elixir.bootlin.com/linux/v7.1-rc7/source/Documentation/devicetree/bindings/submitting-patches.rst#L23 > diff --git a/Documentation/devicetree/bindings/display/panel/lg,sw49410.yaml b/Documentation/devicetree/bindings/display/panel/lg,sw49410.yaml > new file mode 100644 > index 000000000000..4c4bf4d89353 > --- /dev/null > +++ b/Documentation/devicetree/bindings/display/panel/lg,sw49410.yaml > @@ -0,0 +1,79 @@ > +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause > +%YAML 1.2 > +--- > +$id: http://devicetree.org/schemas/display/panel/lg,sw49410.yaml# > +$schema: http://devicetree.org/meta-schemas/core.yaml# > + > +title: LG LH609QH1 MIPI-DSI panel with SW49410 controller > + > +maintainers: > + - Paul Sajna <sajattack@postmarketos.org> > + > +description: > + LG LH609QH1 6.1" 1440x3120 MIPI DSI panel with SW49410 controller found in LG G7 ThinQ smartphone. Please wrap code according to the preferred limit expressed in Kernel coding style (checkpatch is not a coding style description, but only a tool). However don't wrap blindly (see Kernel coding style). > + > +allOf: > + - $ref: panel-common.yaml# > + > +properties: > + compatible: > + items: > + - const: lg,sw49410 > + - const: lg,sw49410-lh609qh1 This is very confusing - why two compatibles and why same devices - both sw49410 - are compatible with each other? > + > + reg: > + maxItems: 1 > + > + backlight: > + description: Backlight device reference Drop property here, not needed. > + > + reset-gpios: > + description: Reset pin reference > + > + vsp-supply: > + description: Positive voltage supply > + > + vsn-supply: > + description: Negative voltage supply > + > +required: > + - compatible > + - reg > + - reset-gpios > + - port > + - vsp-supply > + - vsn-supply > + > +unevaluatedProperties: false > + > +examples: > + - | > + #include <dt-bindings/gpio/gpio.h> > + > + dsi { > + #address-cells = <1>; > + #size-cells = <0>; > + > + panel@0 { > + reg = <0>; > + compatible = "lg,sw49410-lh609qh1"; > + > + backlight = <&pmi8998_wled>; > + reset-gpios = <&tlmm 6 GPIO_ACTIVE_LOW>; > + width-mm = <65>; > + height-mm = <140>; > + > + vsp-supply = <&lab>; > + vsn-supply = <&ibb>; > + > + pinctrl-0 = <&sde_dsi_active &sde_te_active_sleep>; > + pinctrl-1 = <&sde_dsi_sleep &sde_te_active_sleep>; > + pinctrl-names = "default", "sleep"; > + > + port { > + panel_in: endpoint { Messed/inconsistent indentation. Best regards, Krzysztof ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v3 2/4] dt-bindings: display: panel: Add documentation for lg,sw49410-lh609qh1 2026-06-15 0:07 ` [PATCH v3 2/4] dt-bindings: display: panel: Add documentation for lg,sw49410-lh609qh1 Paul Sajna 2026-06-15 0:17 ` sashiko-bot 2026-06-15 5:38 ` Krzysztof Kozlowski @ 2026-06-15 5:39 ` Krzysztof Kozlowski 2 siblings, 0 replies; 12+ messages in thread From: Krzysztof Kozlowski @ 2026-06-15 5:39 UTC (permalink / raw) To: Paul Sajna Cc: Neil Armstrong, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Thierry Reding, Sam Ravnborg, Jessica Zhang, linux-kernel, dri-devel, devicetree, David Heidelberg, phone-devel, Amir Dahan On Sun, Jun 14, 2026 at 05:07:59PM -0700, Paul Sajna wrote: > + dsi { > + #address-cells = <1>; > + #size-cells = <0>; > + > + panel@0 { > + reg = <0>; > + compatible = "lg,sw49410-lh609qh1"; Ah, and you never tested this, so I should not even review it. Be sure you test your code BEFORE you send to mailing list. Our build infrastructure is not a replacement of your testing. Best regards, Krzysztof ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v3 3/4] MAINTAINERS: add Paul Sajna as maintainer for lg,sw49410-lh609qh1 2026-06-15 0:07 [PATCH v3 0/4] Add DRM driver for LG LH609QH1 Panel with SiliconWorks SW49410 DDIC Paul Sajna 2026-06-15 0:07 ` [PATCH v3 1/4] drm: panel: Add LG LH609QH1 Panel with SW49410 controller Paul Sajna 2026-06-15 0:07 ` [PATCH v3 2/4] dt-bindings: display: panel: Add documentation for lg,sw49410-lh609qh1 Paul Sajna @ 2026-06-15 0:08 ` Paul Sajna 2026-06-15 0:08 ` [PATCH v3 4/4] Revert "dt-bindings: display: panel: panel-simple: Add lg,sw49410 compatible" Paul Sajna 3 siblings, 0 replies; 12+ messages in thread From: Paul Sajna @ 2026-06-15 0:08 UTC (permalink / raw) To: Neil Armstrong, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Thierry Reding, Sam Ravnborg, Jessica Zhang, Jessica Zhang Cc: linux-kernel, dri-devel, devicetree, David Heidelberg, phone-devel, Amir Dahan, Paul Sajna Add myself (Paul Sajna) as maintainer for lg,sw49410-lh609qh1 Signed-off-by: Paul Sajna <sajattack@postmarketos.org> --- MAINTAINERS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index c9f2780b2d31..5c043fb66af0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8134,6 +8134,12 @@ T: git https://gitlab.freedesktop.org/drm/misc/kernel.git F: Documentation/devicetree/bindings/display/panel/lg,sw43408.yaml F: drivers/gpu/drm/panel/panel-lg-sw43408.c +DRM DRIVER FOR LG SW49410 PANELS +M: Paul Sajna <sajattack@postmarketos.org> +S: Maintained +F: Documentation/devicetree/bindings/display/panel/lg,sw49410.yaml +F: drivers/gpu/drm/panel/panel-lg-sw49410.c + DRM DRIVER FOR LOGICVC DISPLAY CONTROLLER M: Paul Kocialkowski <paulk@sys-base.io> S: Supported -- 2.54.0 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v3 4/4] Revert "dt-bindings: display: panel: panel-simple: Add lg,sw49410 compatible" 2026-06-15 0:07 [PATCH v3 0/4] Add DRM driver for LG LH609QH1 Panel with SiliconWorks SW49410 DDIC Paul Sajna ` (2 preceding siblings ...) 2026-06-15 0:08 ` [PATCH v3 3/4] MAINTAINERS: add Paul Sajna as maintainer " Paul Sajna @ 2026-06-15 0:08 ` Paul Sajna 2026-06-15 0:17 ` sashiko-bot 2026-06-15 5:40 ` Krzysztof Kozlowski 3 siblings, 2 replies; 12+ messages in thread From: Paul Sajna @ 2026-06-15 0:08 UTC (permalink / raw) To: Neil Armstrong, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Thierry Reding, Sam Ravnborg, Jessica Zhang, Jessica Zhang Cc: linux-kernel, dri-devel, devicetree, David Heidelberg, phone-devel, Amir Dahan, Paul Sajna This reverts commit a74c2e55ab66519ffa2069ac9ae83cd937bff4c4. It isn't actually panel-simple-compatible, and we knew as much by the time this merged, but I guess maintainers needed something to prevent the dt-bindings error going off while I was working on these patches. Signed-off-by: Paul Sajna <sajattack@postmarketos.org> --- Documentation/devicetree/bindings/display/panel/panel-simple.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml index 21453f0d7ce2..58303a767a36 100644 --- a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml +++ b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml @@ -204,8 +204,6 @@ properties: - lemaker,bl035-rgb-002 # LG 7" (800x480 pixels) TFT LCD panel - lg,lb070wv8 - # LG 6.1" (1440x3120) IPS LCD panel - - lg,sw49410 # Logic Technologies LT161010-2NHC 7" WVGA TFT Cap Touch Module - logictechno,lt161010-2nhc # Logic Technologies LT161010-2NHR 7" WVGA TFT Resistive Touch Module -- 2.54.0 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH v3 4/4] Revert "dt-bindings: display: panel: panel-simple: Add lg,sw49410 compatible" 2026-06-15 0:08 ` [PATCH v3 4/4] Revert "dt-bindings: display: panel: panel-simple: Add lg,sw49410 compatible" Paul Sajna @ 2026-06-15 0:17 ` sashiko-bot 2026-06-15 5:40 ` Krzysztof Kozlowski 1 sibling, 0 replies; 12+ messages in thread From: sashiko-bot @ 2026-06-15 0:17 UTC (permalink / raw) To: Paul Sajna; +Cc: conor+dt, dri-devel, robh, devicetree Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: Pre-existing issues: - [High] Missing drm_panel_remove() on the mipi_dsi_attach() error path in probe causes a Use-After-Free. - [High] Panel reset is erroneously asserted before sending DSI sleep commands in the unprepare sequence. -- commit 591497f012912dfaa02eb5ec6c5c1e0d8e61f126 Author: Paul Sajna <sajattack@postmarketos.org> Revert "dt-bindings: display: panel: panel-simple: Add lg,sw49410 compatible" This reverts commit a74c2e55ab66519ffa2069ac9ae83cd937bff4c4. The panel isn't actually panel-simple-compatible. > diff --git a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml > index 3e41ed0ef5d51..1abdc8698a865 100644 > --- a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml > +++ b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml > @@ -200,8 +200,6 @@ properties: > - lemaker,bl035-rgb-002 > # LG 7" (800x480 pixels) TFT LCD panel > - lg,lb070wv8 > - # LG 6.1" (1440x3120) IPS LCD panel > - - lg,sw49410 [Severity: High] This isn't a bug introduced by this patch, but while looking at the sw49410 panel driver code, I noticed a missing drm_panel_remove() on the mipi_dsi_attach() error path in probe which causes a use-after-free: drivers/gpu/drm/panel/panel-lg-sw49410.c:sw49410_panel_probe() { drm_panel_add(&ctx->panel); /* This panel only supports DSC; unconditionally enable it */ dsi->dsc = &ctx->dsc; ... return mipi_dsi_attach(dsi); } If mipi_dsi_attach() fails, the function returns an error without calling drm_panel_remove(). Because ctx was allocated with devm_drm_panel_alloc(), the kernel devres mechanism will free ctx upon probe failure. This leaves a dangling pointer in the global panel_list. Any subsequent operations iterating over panel_list (such as another driver calling drm_panel_get()) will dereference the freed memory, causing a use-after-free kernel panic. Could we add a call to drm_panel_remove() to the error path here? [Severity: High] This is a pre-existing issue, but the panel reset is erroneously asserted before sending DSI sleep commands in the unprepare sequence: drivers/gpu/drm/panel/panel-lg-sw49410.c:sw49410_panel_unprepare() { gpiod_set_value(ctx->reset_gpio, 1); struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi }; mipi_dsi_dcs_set_display_off_multi(&dsi_ctx); mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); } The reset GPIO is asserted (gpiod_set_value(ctx->reset_gpio, 1)) before executing the MIPI DCS sleep commands. Attempting to send MIPI DCS commands to a panel that is held in hardware reset will cause the DSI host to fail to communicate, resulting in severe command timeouts and error logs. The unprepare sequence is functionally broken because the panel cannot gracefully enter sleep mode. Should the panel reset be delayed until after the DSI sleep commands are sent? > # Logic Technologies LT161010-2NHC 7" WVGA TFT Cap Touch Module > - logictechno,lt161010-2nhc -- Sashiko AI review · https://sashiko.dev/#/patchset/20260614-judyln-panel-v3-0-07f4134441bd@postmarketos.org?part=4 ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v3 4/4] Revert "dt-bindings: display: panel: panel-simple: Add lg,sw49410 compatible" 2026-06-15 0:08 ` [PATCH v3 4/4] Revert "dt-bindings: display: panel: panel-simple: Add lg,sw49410 compatible" Paul Sajna 2026-06-15 0:17 ` sashiko-bot @ 2026-06-15 5:40 ` Krzysztof Kozlowski 1 sibling, 0 replies; 12+ messages in thread From: Krzysztof Kozlowski @ 2026-06-15 5:40 UTC (permalink / raw) To: Paul Sajna Cc: Neil Armstrong, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Thierry Reding, Sam Ravnborg, Jessica Zhang, linux-kernel, dri-devel, devicetree, David Heidelberg, phone-devel, Amir Dahan On Sun, Jun 14, 2026 at 05:08:01PM -0700, Paul Sajna wrote: > This reverts commit a74c2e55ab66519ffa2069ac9ae83cd937bff4c4. > > It isn't actually panel-simple-compatible, and we knew as much by the This is not a separate commit. Your work is non-bisectable - this commit leaves undocumented compatible. Best regards, Krzysztof ^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2026-06-15 5:40 UTC | newest] Thread overview: 12+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-06-15 0:07 [PATCH v3 0/4] Add DRM driver for LG LH609QH1 Panel with SiliconWorks SW49410 DDIC Paul Sajna 2026-06-15 0:07 ` [PATCH v3 1/4] drm: panel: Add LG LH609QH1 Panel with SW49410 controller Paul Sajna 2026-06-15 0:18 ` sashiko-bot 2026-06-15 5:40 ` Krzysztof Kozlowski 2026-06-15 0:07 ` [PATCH v3 2/4] dt-bindings: display: panel: Add documentation for lg,sw49410-lh609qh1 Paul Sajna 2026-06-15 0:17 ` sashiko-bot 2026-06-15 5:38 ` Krzysztof Kozlowski 2026-06-15 5:39 ` Krzysztof Kozlowski 2026-06-15 0:08 ` [PATCH v3 3/4] MAINTAINERS: add Paul Sajna as maintainer " Paul Sajna 2026-06-15 0:08 ` [PATCH v3 4/4] Revert "dt-bindings: display: panel: panel-simple: Add lg,sw49410 compatible" Paul Sajna 2026-06-15 0:17 ` sashiko-bot 2026-06-15 5:40 ` Krzysztof Kozlowski
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox