* [PATCH v4 0/5] Add support to 2 panels in bonded-DSI mode
@ 2026-05-21 14:46 Jun Nie
2026-05-21 14:46 ` [PATCH v4 1/5] drm/msm/dsi: support DSC configurations with slice_per_pkt > 1 Jun Nie
` (4 more replies)
0 siblings, 5 replies; 15+ messages in thread
From: Jun Nie @ 2026-05-21 14:46 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, Dmitry Baryshkov, Abhinav Kumar,
Jessica Zhang, Sean Paul, Marijn Suijten, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Neil Armstrong, Rob Herring,
Krzysztof Kozlowski, Conor Dooley
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, devicetree,
Jun Nie, Jonathan Marek
The 2 DSI interfaces may be connected to 2 independent panels in bonded-DSI
mode. Horizontal timing and DSC configuration are adjusted per individual
panel in DSI host side. Support to multiple slice per packet is added for
the device setup to test the usage case. A panel driver is included as an
use case example.
Changes vs v3:
- A panel driver is added as an use case example.
- Move dsc_slice_per_pkt to struct drm_dsc_config.
- Polish commit messages.
- Link to v3: https://lore.kernel.org/all/20250924-dsi-dual-panel-upstream-v3-0-6927284f1098@linaro.org
Changes vs v2:
- Polish commit message to describe usage case and requirements to
panel driver.
- Remove changes in device tree and add dual_panel flag in mipi_dsi_device
to pass information from panel to dsi host.
- Drop the register programming to DSI_VBIF_CTRL, as no issue is seen
in latest test.
- Link to v2: https://lore.kernel.org/r/20250220-dual-dsi-v2-0-6c0038d5a2ef@linaro.org
Change vs v1:
- Add device tree binding for dual panel case in handling frame width for
DSC to avoid breaking existing dual-DSI case.
- Leverage Marijn's patch to configure proper slice per interface in
dsi_update_dsc_timing().
- Polish commit comments.
- Link to v1: https://lore.kernel.org/all/20240829-sm8650-v6-11-hmd-pocf-mdss-quad-upstream-8-v1-0-bdb05b4b5a2e@linaro.org/
Signed-off-by: Jun Nie <jun.nie@linaro.org>
---
Jun Nie (5):
drm/msm/dsi: support DSC configurations with slice_per_pkt > 1
drm/mipi-dsi: Add flag to support dual-panel configurations
drm/msm/dsi: Support dual panel use case with single CRTC
dt-bindings: display: Add Synaptics R63455 panel support
drm/panel: Add driver for Synaptics R63455 DSI panel
.../bindings/display/panel/synaptics,r63455.yaml | 125 ++++
drivers/gpu/drm/msm/dsi/dsi_host.c | 33 +-
drivers/gpu/drm/panel/Kconfig | 9 +
drivers/gpu/drm/panel/Makefile | 1 +
drivers/gpu/drm/panel/panel-synaptics-r63455.c | 631 +++++++++++++++++++++
include/drm/display/drm_dsc.h | 7 +
include/drm/drm_mipi_dsi.h | 2 +
7 files changed, 792 insertions(+), 16 deletions(-)
---
base-commit: 6654f8f33aa6229a90d4401519a62a2bf96cb851
change-id: 20260521-sm8650-7-1-bonded-dsi-7a7d5b70f687
Best regards,
--
Jun Nie <jun.nie@linaro.org>
^ permalink raw reply [flat|nested] 15+ messages in thread* [PATCH v4 1/5] drm/msm/dsi: support DSC configurations with slice_per_pkt > 1 2026-05-21 14:46 [PATCH v4 0/5] Add support to 2 panels in bonded-DSI mode Jun Nie @ 2026-05-21 14:46 ` Jun Nie 2026-05-21 15:08 ` sashiko-bot 2026-05-21 14:46 ` [PATCH v4 2/5] drm/mipi-dsi: Add flag to support dual-panel configurations Jun Nie ` (3 subsequent siblings) 4 siblings, 1 reply; 15+ messages in thread From: Jun Nie @ 2026-05-21 14:46 UTC (permalink / raw) To: Rob Clark, Dmitry Baryshkov, Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Sean Paul, Marijn Suijten, David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Neil Armstrong, Rob Herring, Krzysztof Kozlowski, Conor Dooley Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, devicetree, Jun Nie, Jonathan Marek Some panels require multiple slice to be sent in a single DSC packet. And this feature is a must for specific panels, such as Sharp ls026b3sa06. Add a dsc_slice_per_pkt member into struct drm_dsc_config and support the feature in msm mdss driver. Co-developed-by: Jonathan Marek <jonathan@marek.ca> Signed-off-by: Jonathan Marek <jonathan@marek.ca> Signed-off-by: Jun Nie <jun.nie@linaro.org> --- drivers/gpu/drm/msm/dsi/dsi_host.c | 23 ++++++++--------------- include/drm/display/drm_dsc.h | 7 +++++++ 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index 53ff23f4f68ab..d14b6e41dcd90 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -166,6 +166,7 @@ struct msm_dsi_host { struct drm_display_mode *mode; struct drm_dsc_config *dsc; + unsigned int dsc_slice_per_pkt; /* connected device info */ unsigned int channel; @@ -938,17 +939,10 @@ static void dsi_update_dsc_timing(struct msm_dsi_host *msm_host, bool is_cmd_mod slice_per_intf = dsc->slice_count; total_bytes_per_intf = dsc->slice_chunk_size * slice_per_intf; - bytes_per_pkt = dsc->slice_chunk_size; /* * slice_per_pkt; */ + bytes_per_pkt = dsc->slice_chunk_size * msm_host->dsc_slice_per_pkt; eol_byte_num = total_bytes_per_intf % 3; - - /* - * Typically, pkt_per_line = slice_per_intf * slice_per_pkt. - * - * Since the current driver only supports slice_per_pkt = 1, - * pkt_per_line will be equal to slice per intf for now. - */ - pkt_per_line = slice_per_intf; + pkt_per_line = slice_per_intf / msm_host->dsc_slice_per_pkt; if (is_cmd_mode) /* packet data type */ reg = DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM0_DATATYPE(MIPI_DSI_DCS_LONG_WRITE); @@ -1104,12 +1098,8 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_bonded_dsi) else /* * When DSC is enabled, WC = slice_chunk_size * slice_per_pkt + 1. - * Currently, the driver only supports default value of slice_per_pkt = 1 - * - * TODO: Expand mipi_dsi_device struct to hold slice_per_pkt info - * and adjust DSC math to account for slice_per_pkt. */ - wc = msm_host->dsc->slice_chunk_size + 1; + wc = msm_host->dsc->slice_chunk_size * msm_host->dsc_slice_per_pkt + 1; dsi_write(msm_host, REG_DSI_CMD_MDP_STREAM0_CTRL, DSI_CMD_MDP_STREAM0_CTRL_WORD_COUNT(wc) | @@ -1719,8 +1709,11 @@ static int dsi_host_attach(struct mipi_dsi_host *host, msm_host->lanes = dsi->lanes; msm_host->format = dsi->format; msm_host->mode_flags = dsi->mode_flags; - if (dsi->dsc) + if (dsi->dsc) { msm_host->dsc = dsi->dsc; + /* for backwards compatibility, assume 1 if not set */ + msm_host->dsc_slice_per_pkt = dsi->dsc->dsc_slice_per_pkt ?: 1; + } if (msm_host->format == MIPI_DSI_FMT_RGB101010) { if (!msm_dsi_host_version_geq(msm_host, MSM_DSI_VER_MAJOR_6G, diff --git a/include/drm/display/drm_dsc.h b/include/drm/display/drm_dsc.h index bbbe7438473d3..c522ab3d71853 100644 --- a/include/drm/display/drm_dsc.h +++ b/include/drm/display/drm_dsc.h @@ -267,6 +267,13 @@ struct drm_dsc_config { * Offset adjustment for second line in Native 4:2:0 mode */ u16 second_line_offset_adj; + + /** + * @dsc_slice_per_pkt: + * Number of DSC slices to be sent in a single packet. This is not + * part of DSC standard, and only used in some DSI panels so far. + */ + unsigned int dsc_slice_per_pkt; }; /** -- 2.43.0 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH v4 1/5] drm/msm/dsi: support DSC configurations with slice_per_pkt > 1 2026-05-21 14:46 ` [PATCH v4 1/5] drm/msm/dsi: support DSC configurations with slice_per_pkt > 1 Jun Nie @ 2026-05-21 15:08 ` sashiko-bot 0 siblings, 0 replies; 15+ messages in thread From: sashiko-bot @ 2026-05-21 15:08 UTC (permalink / raw) To: Jun Nie; +Cc: robh, conor+dt, devicetree Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: Pre-existing issues: - [High] Failure to clear `msm_host->dsc` and `dsc_slice_per_pkt` when a panel without DSC is attached leads to a potential use-after-free. -- commit 4b3fdd757a84f263ad4c869c8ef48cdc07ee2b22 Author: Jun Nie <jun.nie@linaro.org> drm/msm/dsi: support DSC configurations with slice_per_pkt > 1 This commit adds support for sending multiple DSC slices in a single packet for the MSM DSI driver. It introduces a dsc_slice_per_pkt member into struct drm_dsc_config and updates the relevant timing calculations. > diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c > index 565d425f88b86..10589389650fc 100644 > --- a/drivers/gpu/drm/msm/dsi/dsi_host.c > +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c [ ... ] > @@ -1718,8 +1708,11 @@ static int dsi_host_attach(struct mipi_dsi_host *host, > msm_host->lanes = dsi->lanes; > msm_host->format = dsi->format; > msm_host->mode_flags = dsi->mode_flags; > - if (dsi->dsc) > + if (dsi->dsc) { > msm_host->dsc = dsi->dsc; > + /* for backwards compatibility, assume 1 if not set */ > + msm_host->dsc_slice_per_pkt = dsi->dsc->dsc_slice_per_pkt ?: 1; > + } [Severity: High] This is a pre-existing issue, but does failing to clear msm_host->dsc and dsc_slice_per_pkt when a panel without DSC is attached lead to a potential use-after-free? When a panel driver is unbound, the DRM pipeline is torn down, and the panel's memory (including the embedded drm_dsc_config structure) is freed. However, the msm_dsi_host structure persists in memory because it belongs to the DSI host controller driver. If a new panel without DSC is subsequently bound, dsi->dsc will be NULL, causing dsi_host_attach() to skip the assignment and leave msm_host->dsc pointing to the freed memory. When the display is later enabled, dsi_timing_setup() executes if (msm_host->dsc) and performs a use-after-free write (dsc->pic_width = mode->hdisplay;). Since this patch extends this pattern to the newly added dsc_slice_per_pkt field, should there be an else branch to clear these fields when dsi->dsc is NULL? -- Sashiko AI review · https://sashiko.dev/#/patchset/20260521-sm8650-7-1-bonded-dsi-v4-0-a4dd5e0850f1@linaro.org?part=1 ^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v4 2/5] drm/mipi-dsi: Add flag to support dual-panel configurations 2026-05-21 14:46 [PATCH v4 0/5] Add support to 2 panels in bonded-DSI mode Jun Nie 2026-05-21 14:46 ` [PATCH v4 1/5] drm/msm/dsi: support DSC configurations with slice_per_pkt > 1 Jun Nie @ 2026-05-21 14:46 ` Jun Nie 2026-05-21 15:20 ` sashiko-bot 2026-05-21 14:46 ` [PATCH v4 3/5] drm/msm/dsi: Support dual panel use case with single CRTC Jun Nie ` (2 subsequent siblings) 4 siblings, 1 reply; 15+ messages in thread From: Jun Nie @ 2026-05-21 14:46 UTC (permalink / raw) To: Rob Clark, Dmitry Baryshkov, Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Sean Paul, Marijn Suijten, David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Neil Armstrong, Rob Herring, Krzysztof Kozlowski, Conor Dooley Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, devicetree, Jun Nie Some devices treat two independent physical DSI panels as a single logical panel from the CRTC's perspective. However, two separate DSI hosts are still required to drive the panels individually. Introduce a `dual_panel` flag to the `mipi_dsi_device` struct. This allows a panel driver to inform the DSI host that it is part of a dual-panel setup, enabling the host to coordinate both physical displays as one. Signed-off-by: Jun Nie <jun.nie@linaro.org> --- include/drm/drm_mipi_dsi.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h index 2ab651a36115d..889ef1421207a 100644 --- a/include/drm/drm_mipi_dsi.h +++ b/include/drm/drm_mipi_dsi.h @@ -169,6 +169,7 @@ struct mipi_dsi_device_info { * @host: DSI host for this peripheral * @dev: driver model device node for this peripheral * @attached: the DSI device has been successfully attached + * @dual_panel: the DSI device is one instance of dual panel * @name: DSI peripheral chip type * @channel: virtual channel assigned to the peripheral * @format: pixel format for video mode @@ -186,6 +187,7 @@ struct mipi_dsi_device { struct mipi_dsi_host *host; struct device dev; bool attached; + bool dual_panel; char name[DSI_DEV_NAME_SIZE]; unsigned int channel; -- 2.43.0 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH v4 2/5] drm/mipi-dsi: Add flag to support dual-panel configurations 2026-05-21 14:46 ` [PATCH v4 2/5] drm/mipi-dsi: Add flag to support dual-panel configurations Jun Nie @ 2026-05-21 15:20 ` sashiko-bot 0 siblings, 0 replies; 15+ messages in thread From: sashiko-bot @ 2026-05-21 15:20 UTC (permalink / raw) To: Jun Nie; +Cc: robh, conor+dt, devicetree Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [Low] Adding a `dual_panel` flag to `mipi_dsi_device` forces individual panel drivers to handle system-level display topology, violating the separation of concerns. -- commit f6f95d24bc09251a7384b7ecd49f09b146258523 Author: Jun Nie <jun.nie@linaro.org> drm/mipi-dsi: Add flag to support dual-panel configurations This commit introduces a dual_panel flag to the mipi_dsi_device struct. This allows a panel driver to inform the DSI host that it is part of a dual-panel setup, treating two independent physical panels as a single logical display. > diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h > index 2ab651a36115d..889ef1421207a 100644 > --- a/include/drm/drm_mipi_dsi.h > +++ b/include/drm/drm_mipi_dsi.h [ ... ] > @@ -186,6 +187,7 @@ struct mipi_dsi_device { > struct mipi_dsi_host *host; > struct device dev; > bool attached; > + bool dual_panel; [Severity: Low] Does introducing this flag to the mipi_dsi_device struct force individual panel drivers to manage system-level display topology? Grouping two independent physical panels into a single logical display is a system-level integration detail. Typically, panel drivers should not be responsible for understanding system-wide topologies. Could this information be determined by the display framework instead, such as by parsing the Device Tree graph to see if two DSI hosts are routed to a single CRTC? This might prevent an architectural layering violation and maintain driver reusability across different system configurations. -- Sashiko AI review · https://sashiko.dev/#/patchset/20260521-sm8650-7-1-bonded-dsi-v4-0-a4dd5e0850f1@linaro.org?part=2 ^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v4 3/5] drm/msm/dsi: Support dual panel use case with single CRTC 2026-05-21 14:46 [PATCH v4 0/5] Add support to 2 panels in bonded-DSI mode Jun Nie 2026-05-21 14:46 ` [PATCH v4 1/5] drm/msm/dsi: support DSC configurations with slice_per_pkt > 1 Jun Nie 2026-05-21 14:46 ` [PATCH v4 2/5] drm/mipi-dsi: Add flag to support dual-panel configurations Jun Nie @ 2026-05-21 14:46 ` Jun Nie 2026-05-21 15:50 ` sashiko-bot 2026-05-21 14:46 ` [PATCH v4 4/5] dt-bindings: display: Add Synaptics R63455 panel support Jun Nie 2026-05-21 14:46 ` [PATCH v4 5/5] drm/panel: Add driver for Synaptics R63455 DSI panel Jun Nie 4 siblings, 1 reply; 15+ messages in thread From: Jun Nie @ 2026-05-21 14:46 UTC (permalink / raw) To: Rob Clark, Dmitry Baryshkov, Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Sean Paul, Marijn Suijten, David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Neil Armstrong, Rob Herring, Krzysztof Kozlowski, Conor Dooley Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, devicetree, Jun Nie Support a hardware configuration where two independent DSI panels are driven by a single, synchronous CRTC. This configuration uses a bonded DSI link to provide a unified vblank for both displays. This allows application software to treat the two displays as a single, wide framebuffer with a synchronized refresh cycle, simplifying rendering logic for side-by-side panel arrangements. At the DSI host level, the frame width for each link must be that of an individual panel. The driver therefore halves the CRTC's horizontal resolution before configuring the DSI host and any DSC encoders, ensuring each panel receives the correct half of the framebuffer. While the DSI panel driver should manage two panels togehter. 1. During probe, the driver finds the sibling dsi host via device tree phandle and register the 2nd panel to get another mipi_dsi_device. 2. Set dual_panel flag on both mipi_dsi_device. 3. Prepare DSC data per requirement from single panel. 4. All DSI commands should be send on every DSI link. 5. Handle power supply for 2 panels in one shot, the same is true to brightness. 6. From the CRTC's perspective, the two panels appear as one wide display. The driver exposes a DRM mode where the horizontal timings (hdisplay, hsync_start, etc.) are doubled, while the vertical timings remain those of a single panel. Because 2 panels are expected to be mounted in left/right position. To maintain synchronization, both DSI links are configured to share a single clock source, with the DSI1 controller using the clock provided to DSI0 as below. &mdss_dsi1 { assigned-clocks = <&dispcc DISP_CC_MDSS_BYTE1_CLK_SRC>, <&dispcc DISP_CC_MDSS_PCLK1_CLK_SRC>; assigned-clock-parents = <&mdss_dsi0_phy 0>, <&mdss_dsi0_phy 1>; } Signed-off-by: Jun Nie <jun.nie@linaro.org> --- drivers/gpu/drm/msm/dsi/dsi_host.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index d14b6e41dcd90..4d7ac01aa393d 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -186,6 +186,7 @@ struct msm_dsi_host { bool registered; bool power_on; bool enabled; + bool is_dual_panel; int irq; }; @@ -1024,7 +1025,10 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_bonded_dsi) return; } - dsc->pic_width = mode->hdisplay; + if (msm_host->is_dual_panel) + dsc->pic_width = hdisplay; + else + dsc->pic_width = mode->hdisplay; dsc->pic_height = mode->vdisplay; DBG("Mode %dx%d\n", dsc->pic_width, dsc->pic_height); @@ -1705,6 +1709,7 @@ static int dsi_host_attach(struct mipi_dsi_host *host, if (dsi->lanes > msm_host->num_data_lanes) return -EINVAL; + msm_host->is_dual_panel = dsi->dual_panel; msm_host->channel = dsi->channel; msm_host->lanes = dsi->lanes; msm_host->format = dsi->format; @@ -2596,6 +2601,9 @@ enum drm_mode_status msm_dsi_host_check_dsc(struct mipi_dsi_host *host, if (!msm_host->dsc) return MODE_OK; + if (msm_host->is_dual_panel) + pic_width = mode->hdisplay / 2; + if (pic_width % dsc->slice_width) { pr_err("DSI: pic_width %d has to be multiple of slice %d\n", pic_width, dsc->slice_width); -- 2.43.0 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH v4 3/5] drm/msm/dsi: Support dual panel use case with single CRTC 2026-05-21 14:46 ` [PATCH v4 3/5] drm/msm/dsi: Support dual panel use case with single CRTC Jun Nie @ 2026-05-21 15:50 ` sashiko-bot 0 siblings, 0 replies; 15+ messages in thread From: sashiko-bot @ 2026-05-21 15:50 UTC (permalink / raw) To: Jun Nie; +Cc: devicetree, conor+dt, robh Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [High] Halving `dsc->pic_width` for dual panels causes the DPU DSC encoder to incorrectly program the DSC hardware, resulting in a halved processing width and hardware underflow. -- commit d23a05783cbe32106f4e17b417f7304f721a2609 Author: Jun Nie <jun.nie@linaro.org> drm/msm/dsi: Support dual panel use case with single CRTC This commit adds support for a hardware configuration where two independent DSI panels are driven by a single, synchronous CRTC. The driver halves the CRTC's horizontal resolution before configuring the DSI host and any DSC encoders to ensure each panel receives the proper half of the framebuffer. > diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c > index 10589389650fc..4a391cdd4030a 100644 > --- a/drivers/gpu/drm/msm/dsi/dsi_host.c > +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c [ ... ] > @@ -1024,7 +1025,10 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_bonded_dsi) > return; > } > > - dsc->pic_width = mode->hdisplay; > + if (msm_host->is_dual_panel) > + dsc->pic_width = hdisplay; > + else > + dsc->pic_width = mode->hdisplay; [Severity: High] Can setting dsc->pic_width to the halved hdisplay cause the DPU DSC encoder to incorrectly program the hardware? The struct drm_dsc_config is shared with the DPU encoder driver, which expects dsc->pic_width to represent the total picture width across all DSC encoders for the CRTC. If the DPU driver calculates the encoder processing width by dividing this value by num_dsc (which is 2 for a dual DSI setup), won't this result in a processing width that is a quarter of the total CRTC width? This looks like it could lead to incorrect pipeline delay calculations and cause the hardware to process only half the intended width, potentially leading to display corruption and hardware pipeline underflows. > dsc->pic_height = mode->vdisplay; > DBG("Mode %dx%d\n", dsc->pic_width, dsc->pic_height); > -- Sashiko AI review · https://sashiko.dev/#/patchset/20260521-sm8650-7-1-bonded-dsi-v4-0-a4dd5e0850f1@linaro.org?part=3 ^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v4 4/5] dt-bindings: display: Add Synaptics R63455 panel support 2026-05-21 14:46 [PATCH v4 0/5] Add support to 2 panels in bonded-DSI mode Jun Nie ` (2 preceding siblings ...) 2026-05-21 14:46 ` [PATCH v4 3/5] drm/msm/dsi: Support dual panel use case with single CRTC Jun Nie @ 2026-05-21 14:46 ` Jun Nie 2026-05-21 16:07 ` sashiko-bot ` (3 more replies) 2026-05-21 14:46 ` [PATCH v4 5/5] drm/panel: Add driver for Synaptics R63455 DSI panel Jun Nie 4 siblings, 4 replies; 15+ messages in thread From: Jun Nie @ 2026-05-21 14:46 UTC (permalink / raw) To: Rob Clark, Dmitry Baryshkov, Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Sean Paul, Marijn Suijten, David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Neil Armstrong, Rob Herring, Krzysztof Kozlowski, Conor Dooley Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, devicetree, Jun Nie Add support for the dual-panel system found in the virtual reality device. This system consists of two physical 2160x2160 panels, each connected via a MIPI DSI interface. The backlight is managed through DSI link. Signed-off-by: Jun Nie <jun.nie@linaro.org> --- .../bindings/display/panel/synaptics,r63455.yaml | 125 +++++++++++++++++++++ 1 file changed, 125 insertions(+) diff --git a/Documentation/devicetree/bindings/display/panel/synaptics,r63455.yaml b/Documentation/devicetree/bindings/display/panel/synaptics,r63455.yaml new file mode 100644 index 0000000000000..a94b355ed9557 --- /dev/null +++ b/Documentation/devicetree/bindings/display/panel/synaptics,r63455.yaml @@ -0,0 +1,125 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/panel/synaptics,r63455.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Synaptics R63455 based dual 2160x2160 MIPI-DSI Panel + +maintainers: + - Jun Nie <jun.nie@linaro.org> + +description: + Synaptics R63455 is a Virtual Reality Display Driver and VR Bridge, used in + pair in Headset devices. The Virtual Reality Display complex is composed of + two strictly identical display panels, each driven by its own DSI interface + but forms a single virtual display for the human eye perception and thus + requires a strict synchronization of the two display panel content update. + +allOf: + - $ref: panel-common.yaml# + +properties: + compatible: + items: + - enum: + - sharp,ls026b3sa06 + - boe,vs026c4m-n52-6000 + - const: synaptics,r63455 + + reset-gpios: + maxItems: 2 + description: 2 reset pins for 2 physical panels + + left-pos-supply: + description: Positive 5.7V supply for left panel + + right-pos-supply: + description: Positive 5.7V supply for right panel + + left-neg-supply: + description: Negative 5.7V supply for left panel + + right-neg-supply: + description: Negative 5.7V supply for right panel + + left-backlight-supply: + description: Backlight 21V supply for left panel + + right-backlight-supply: + description: Backlight 21V supply for right panel + + vdda-supply: + description: core 1.8V supply for panels + + ports: $ref: /schemas/graph.yaml#/properties/ports + +required: + - compatible + - reset-gpios + - left-pos-supply + - left-neg-supply + - right-pos-supply + - right-neg-supply + - left-backlight-supply + - right-backlight-supply + - vdda-supply + +additionalProperties: false + +examples: + - | + #include <dt-bindings/gpio/gpio.h> + + &mdss_dsi0 { + vdda-supply = <&vreg_l3i_1p2>; + status = "okay"; + + qcom,dual-dsi-mode; + qcom,master-dsi; + + panel: panel@0 { + compatible = "sharp,ls026b3sa06", "synaptics,r63455"; + reg = <0>; + + reset-gpios = <&pm8550_gpios 3 GPIO_ACTIVE_HIGH>, + <&pm8550_gpios 11 GPIO_ACTIVE_HIGH>; + + left-pos-supply = <&vpos_left>; + left-neg-supply = <&vneg_left>; + right-pos-supply = <&vpos_right>; + right-neg-supply = <&vneg_right>; + left-backlight-supply = <&backlight_left>; + right-backlight-supply = <&backlight_right>; + + vdda-supply = <&vreg_l12b_1p8>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + panel0_in: endpoint { + remote-endpoint = <&mdss_dsi0_out>; + }; + }; + + port@1 { + reg = <1>; + panel1_in: endpoint { + remote-endpoint = <&mdss_dsi1_out>; + }; + }; + }; + }; + + &mdss_dsi0_out { + remote-endpoint = <&panel0_in>; + data-lanes = <0 1 2>; + }; + + &mdss_dsi1_out { + remote-endpoint = <&panel1_in>; + data-lanes = <0 1 2>; + }; +... -- 2.43.0 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH v4 4/5] dt-bindings: display: Add Synaptics R63455 panel support 2026-05-21 14:46 ` [PATCH v4 4/5] dt-bindings: display: Add Synaptics R63455 panel support Jun Nie @ 2026-05-21 16:07 ` sashiko-bot 2026-05-21 19:45 ` Conor Dooley ` (2 subsequent siblings) 3 siblings, 0 replies; 15+ messages in thread From: sashiko-bot @ 2026-05-21 16:07 UTC (permalink / raw) To: Jun Nie; +Cc: conor+dt, devicetree, robh Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider: - [Low] Invalid inline mapping for `$ref` under `ports` property. - [Low] The `reg` property is used in the device tree example but omitted from the schema definitions. - [Low] Missing closing brace for the panel device node in the DTS example. - [Low] The `reset-gpios` property's `maxItems: 2` constraint conflicts with the strictly enforced `maxItems: 1` inherited from `panel-common.yaml`. -- commit 5bb531a3ba9addcc1e532a73333c359429ef1ea6 Author: Jun Nie <jun.nie@linaro.org> Subject: dt-bindings: display: Add Synaptics R63455 panel support Add support for the dual-panel system found in the virtual reality device. This system consists of two physical 2160x2160 panels, each connected via a MIPI DSI interface. > diff --git a/Documentation/devicetree/bindings/display/panel/synaptics,r63455.yaml b/Documentation/devicetree/bindings/display/panel/synaptics,r63455.yaml > new file mode 100644 > index 0000000000000..a94b355ed9557 > --- /dev/null > +++ b/Documentation/devicetree/bindings/display/panel/synaptics,r63455.yaml [ ... ] > +allOf: > + - $ref: panel-common.yaml# > + > +properties: > + compatible: > + items: > + - enum: > + - sharp,ls026b3sa06 > + - boe,vs026c4m-n52-6000 > + - const: synaptics,r63455 > + > + reset-gpios: > + maxItems: 2 [Severity: Low] Will this conflict with panel-common.yaml? Since panel-common.yaml is included via allOf, and it restricts reset-gpios to maxItems: 1, a device tree providing two GPIOs will fail validation against the inherited schema. The local relaxation to maxItems: 2 cannot override the stricter requirement from panel-common.yaml. > + description: 2 reset pins for 2 physical panels [ ... ] > + vdda-supply: > + description: core 1.8V supply for panels > + > + ports: $ref: /schemas/graph.yaml#/properties/ports [Severity: Low] Does this syntax cause a YAML parser error? In YAML, a colon followed by a space indicates a mapping value, and a plain scalar cannot contain an unquoted colon-space sequence. Should the $ref be placed on a new line with proper indentation? > + > +required: > + - compatible [ ... ] > +additionalProperties: false > + > +examples: > + - | > + #include <dt-bindings/gpio/gpio.h> > + > + &mdss_dsi0 { > + vdda-supply = <&vreg_l3i_1p2>; > + status = "okay"; > + > + qcom,dual-dsi-mode; > + qcom,master-dsi; > + > + panel: panel@0 { > + compatible = "sharp,ls026b3sa06", "synaptics,r63455"; > + reg = <0>; [Severity: Low] Should the reg property be explicitly defined in the local schema properties block? It is used here in the example but omitted from the schema definitions. Since additionalProperties is false, dt_binding_check will fail with an undocumented property error. > + > + reset-gpios = <&pm8550_gpios 3 GPIO_ACTIVE_HIGH>, [ ... ] > + ports { > + #address-cells = <1>; > + #size-cells = <0>; > + port@0 { > + reg = <0>; > + panel0_in: endpoint { > + remote-endpoint = <&mdss_dsi0_out>; > + }; > + }; > + > + port@1 { > + reg = <1>; > + panel1_in: endpoint { > + remote-endpoint = <&mdss_dsi1_out>; > + }; > + }; > + }; > + }; [Severity: Low] Is there a missing closing brace for the panel node here? The brace indented at 12 spaces closes the ports subnode, and the next brace indented at 4 spaces closes the root mdss_dsi0 node. The lack of an 8-space indented closing brace for the panel node will cause a syntax error from the Device Tree Compiler. -- Sashiko AI review · https://sashiko.dev/#/patchset/20260521-sm8650-7-1-bonded-dsi-v4-0-a4dd5e0850f1@linaro.org?part=4 ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v4 4/5] dt-bindings: display: Add Synaptics R63455 panel support 2026-05-21 14:46 ` [PATCH v4 4/5] dt-bindings: display: Add Synaptics R63455 panel support Jun Nie 2026-05-21 16:07 ` sashiko-bot @ 2026-05-21 19:45 ` Conor Dooley 2026-05-21 20:24 ` Dmitry Baryshkov 2026-05-21 20:46 ` Rob Herring (Arm) 3 siblings, 0 replies; 15+ messages in thread From: Conor Dooley @ 2026-05-21 19:45 UTC (permalink / raw) To: Jun Nie Cc: Rob Clark, Dmitry Baryshkov, Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Sean Paul, Marijn Suijten, David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Neil Armstrong, Rob Herring, Krzysztof Kozlowski, Conor Dooley, linux-arm-msm, dri-devel, freedreno, linux-kernel, devicetree [-- Attachment #1: Type: text/plain, Size: 4787 bytes --] On Thu, May 21, 2026 at 10:46:06PM +0800, Jun Nie wrote: > Add support for the dual-panel system found in the virtual reality device. > This system consists of two physical 2160x2160 panels, each connected via > a MIPI DSI interface. The backlight is managed through DSI link. > > Signed-off-by: Jun Nie <jun.nie@linaro.org> > --- > .../bindings/display/panel/synaptics,r63455.yaml | 125 +++++++++++++++++++++ > 1 file changed, 125 insertions(+) > > diff --git a/Documentation/devicetree/bindings/display/panel/synaptics,r63455.yaml b/Documentation/devicetree/bindings/display/panel/synaptics,r63455.yaml > new file mode 100644 > index 0000000000000..a94b355ed9557 > --- /dev/null > +++ b/Documentation/devicetree/bindings/display/panel/synaptics,r63455.yaml > @@ -0,0 +1,125 @@ > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) > +%YAML 1.2 > +--- > +$id: http://devicetree.org/schemas/display/panel/synaptics,r63455.yaml# > +$schema: http://devicetree.org/meta-schemas/core.yaml# > + > +title: Synaptics R63455 based dual 2160x2160 MIPI-DSI Panel > + > +maintainers: > + - Jun Nie <jun.nie@linaro.org> > + > +description: > + Synaptics R63455 is a Virtual Reality Display Driver and VR Bridge, used in > + pair in Headset devices. The Virtual Reality Display complex is composed of > + two strictly identical display panels, each driven by its own DSI interface > + but forms a single virtual display for the human eye perception and thus > + requires a strict synchronization of the two display panel content update. > + > +allOf: > + - $ref: panel-common.yaml# > + > +properties: > + compatible: > + items: > + - enum: > + - sharp,ls026b3sa06 > + - boe,vs026c4m-n52-6000 > + - const: synaptics,r63455 > + > + reset-gpios: > + maxItems: 2 > + description: 2 reset pins for 2 physical panels > + > + left-pos-supply: > + description: Positive 5.7V supply for left panel > + > + right-pos-supply: > + description: Positive 5.7V supply for right panel > + > + left-neg-supply: > + description: Negative 5.7V supply for left panel > + > + right-neg-supply: > + description: Negative 5.7V supply for right panel > + > + left-backlight-supply: > + description: Backlight 21V supply for left panel > + > + right-backlight-supply: > + description: Backlight 21V supply for right panel > + > + vdda-supply: > + description: core 1.8V supply for panels > + > + ports: $ref: /schemas/graph.yaml#/properties/ports Missing a newline in this, but also probably missing going into more detail about the ports themselves. Sashiko complaints look valid. pw-bot: changes-requested Thanks, Conor. > + > +required: > + - compatible > + - reset-gpios > + - left-pos-supply > + - left-neg-supply > + - right-pos-supply > + - right-neg-supply > + - left-backlight-supply > + - right-backlight-supply > + - vdda-supply > + > +additionalProperties: false > + > +examples: > + - | > + #include <dt-bindings/gpio/gpio.h> > + > + &mdss_dsi0 { > + vdda-supply = <&vreg_l3i_1p2>; > + status = "okay"; > + > + qcom,dual-dsi-mode; > + qcom,master-dsi; > + > + panel: panel@0 { > + compatible = "sharp,ls026b3sa06", "synaptics,r63455"; > + reg = <0>; > + > + reset-gpios = <&pm8550_gpios 3 GPIO_ACTIVE_HIGH>, > + <&pm8550_gpios 11 GPIO_ACTIVE_HIGH>; > + > + left-pos-supply = <&vpos_left>; > + left-neg-supply = <&vneg_left>; > + right-pos-supply = <&vpos_right>; > + right-neg-supply = <&vneg_right>; > + left-backlight-supply = <&backlight_left>; > + right-backlight-supply = <&backlight_right>; > + > + vdda-supply = <&vreg_l12b_1p8>; > + > + ports { > + #address-cells = <1>; > + #size-cells = <0>; > + port@0 { > + reg = <0>; > + panel0_in: endpoint { > + remote-endpoint = <&mdss_dsi0_out>; > + }; > + }; > + > + port@1 { > + reg = <1>; > + panel1_in: endpoint { > + remote-endpoint = <&mdss_dsi1_out>; > + }; > + }; > + }; > + }; > + > + &mdss_dsi0_out { > + remote-endpoint = <&panel0_in>; > + data-lanes = <0 1 2>; > + }; > + > + &mdss_dsi1_out { > + remote-endpoint = <&panel1_in>; > + data-lanes = <0 1 2>; > + }; > +... > > -- > 2.43.0 > [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 228 bytes --] ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v4 4/5] dt-bindings: display: Add Synaptics R63455 panel support 2026-05-21 14:46 ` [PATCH v4 4/5] dt-bindings: display: Add Synaptics R63455 panel support Jun Nie 2026-05-21 16:07 ` sashiko-bot 2026-05-21 19:45 ` Conor Dooley @ 2026-05-21 20:24 ` Dmitry Baryshkov 2026-05-22 6:32 ` Neil Armstrong 2026-05-21 20:46 ` Rob Herring (Arm) 3 siblings, 1 reply; 15+ messages in thread From: Dmitry Baryshkov @ 2026-05-21 20:24 UTC (permalink / raw) To: Jun Nie Cc: Rob Clark, Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Sean Paul, Marijn Suijten, David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Neil Armstrong, Rob Herring, Krzysztof Kozlowski, Conor Dooley, linux-arm-msm, dri-devel, freedreno, linux-kernel, devicetree On Thu, May 21, 2026 at 10:46:06PM +0800, Jun Nie wrote: > Add support for the dual-panel system found in the virtual reality device. > This system consists of two physical 2160x2160 panels, each connected via > a MIPI DSI interface. The backlight is managed through DSI link. > > Signed-off-by: Jun Nie <jun.nie@linaro.org> > --- > .../bindings/display/panel/synaptics,r63455.yaml | 125 +++++++++++++++++++++ > 1 file changed, 125 insertions(+) > > diff --git a/Documentation/devicetree/bindings/display/panel/synaptics,r63455.yaml b/Documentation/devicetree/bindings/display/panel/synaptics,r63455.yaml > new file mode 100644 > index 0000000000000..a94b355ed9557 > --- /dev/null > +++ b/Documentation/devicetree/bindings/display/panel/synaptics,r63455.yaml > @@ -0,0 +1,125 @@ > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) > +%YAML 1.2 > +--- > +$id: http://devicetree.org/schemas/display/panel/synaptics,r63455.yaml# > +$schema: http://devicetree.org/meta-schemas/core.yaml# > + > +title: Synaptics R63455 based dual 2160x2160 MIPI-DSI Panel > + > +maintainers: > + - Jun Nie <jun.nie@linaro.org> > + > +description: > + Synaptics R63455 is a Virtual Reality Display Driver and VR Bridge, used in > + pair in Headset devices. The Virtual Reality Display complex is composed of > + two strictly identical display panels, each driven by its own DSI interface > + but forms a single virtual display for the human eye perception and thus > + requires a strict synchronization of the two display panel content update. > + > +allOf: > + - $ref: panel-common.yaml# > + > +properties: > + compatible: > + items: > + - enum: > + - sharp,ls026b3sa06 > + - boe,vs026c4m-n52-6000 > + - const: synaptics,r63455 > + > + reset-gpios: > + maxItems: 2 > + description: 2 reset pins for 2 physical panels > + > + left-pos-supply: > + description: Positive 5.7V supply for left panel So, is the R63455 driving both panels or are there two panels, each having R63455 controller? What if somebody gets a single Sharp panel and wants to use it in their device? How will it match these bindings? > + > + right-pos-supply: > + description: Positive 5.7V supply for right panel > + > + left-neg-supply: > + description: Negative 5.7V supply for left panel > + > + right-neg-supply: > + description: Negative 5.7V supply for right panel > + > + left-backlight-supply: > + description: Backlight 21V supply for left panel > + > + right-backlight-supply: > + description: Backlight 21V supply for right panel > + > + vdda-supply: > + description: core 1.8V supply for panels > + > + ports: $ref: /schemas/graph.yaml#/properties/ports > + > +required: > + - compatible > + - reset-gpios > + - left-pos-supply > + - left-neg-supply > + - right-pos-supply > + - right-neg-supply > + - left-backlight-supply > + - right-backlight-supply > + - vdda-supply > + > +additionalProperties: false > + > +examples: > + - | > + #include <dt-bindings/gpio/gpio.h> > + > + &mdss_dsi0 { Please drop the MDSS specifics, there should be one (or two) DSI busses, driving your panels. The rests are details which are not necessary for the example. > + vdda-supply = <&vreg_l3i_1p2>; > + status = "okay"; > + > + qcom,dual-dsi-mode; > + qcom,master-dsi; > + > + panel: panel@0 { > + compatible = "sharp,ls026b3sa06", "synaptics,r63455"; > + reg = <0>; > + > + reset-gpios = <&pm8550_gpios 3 GPIO_ACTIVE_HIGH>, > + <&pm8550_gpios 11 GPIO_ACTIVE_HIGH>; > + > + left-pos-supply = <&vpos_left>; > + left-neg-supply = <&vneg_left>; > + right-pos-supply = <&vpos_right>; > + right-neg-supply = <&vneg_right>; > + left-backlight-supply = <&backlight_left>; > + right-backlight-supply = <&backlight_right>; > + > + vdda-supply = <&vreg_l12b_1p8>; > + > + ports { > + #address-cells = <1>; > + #size-cells = <0>; > + port@0 { > + reg = <0>; > + panel0_in: endpoint { > + remote-endpoint = <&mdss_dsi0_out>; What is mdss_dsi0_out? > + }; > + }; > + > + port@1 { > + reg = <1>; > + panel1_in: endpoint { > + remote-endpoint = <&mdss_dsi1_out>; > + }; > + }; > + }; > + }; > + > + &mdss_dsi0_out { > + remote-endpoint = <&panel0_in>; > + data-lanes = <0 1 2>; > + }; > + > + &mdss_dsi1_out { > + remote-endpoint = <&panel1_in>; > + data-lanes = <0 1 2>; > + }; > +... > > -- > 2.43.0 > -- With best wishes Dmitry ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v4 4/5] dt-bindings: display: Add Synaptics R63455 panel support 2026-05-21 20:24 ` Dmitry Baryshkov @ 2026-05-22 6:32 ` Neil Armstrong 0 siblings, 0 replies; 15+ messages in thread From: Neil Armstrong @ 2026-05-22 6:32 UTC (permalink / raw) To: Dmitry Baryshkov, Jun Nie Cc: Rob Clark, Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Sean Paul, Marijn Suijten, David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Rob Herring, Krzysztof Kozlowski, Conor Dooley, linux-arm-msm, dri-devel, freedreno, linux-kernel, devicetree On 5/21/26 22:24, Dmitry Baryshkov wrote: > On Thu, May 21, 2026 at 10:46:06PM +0800, Jun Nie wrote: >> Add support for the dual-panel system found in the virtual reality device. >> This system consists of two physical 2160x2160 panels, each connected via >> a MIPI DSI interface. The backlight is managed through DSI link. >> >> Signed-off-by: Jun Nie <jun.nie@linaro.org> >> --- >> .../bindings/display/panel/synaptics,r63455.yaml | 125 +++++++++++++++++++++ >> 1 file changed, 125 insertions(+) >> >> diff --git a/Documentation/devicetree/bindings/display/panel/synaptics,r63455.yaml b/Documentation/devicetree/bindings/display/panel/synaptics,r63455.yaml >> new file mode 100644 >> index 0000000000000..a94b355ed9557 >> --- /dev/null >> +++ b/Documentation/devicetree/bindings/display/panel/synaptics,r63455.yaml >> @@ -0,0 +1,125 @@ >> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) >> +%YAML 1.2 >> +--- >> +$id: http://devicetree.org/schemas/display/panel/synaptics,r63455.yaml# >> +$schema: http://devicetree.org/meta-schemas/core.yaml# >> + >> +title: Synaptics R63455 based dual 2160x2160 MIPI-DSI Panel >> + >> +maintainers: >> + - Jun Nie <jun.nie@linaro.org> >> + >> +description: >> + Synaptics R63455 is a Virtual Reality Display Driver and VR Bridge, used in >> + pair in Headset devices. The Virtual Reality Display complex is composed of >> + two strictly identical display panels, each driven by its own DSI interface >> + but forms a single virtual display for the human eye perception and thus >> + requires a strict synchronization of the two display panel content update. >> + >> +allOf: >> + - $ref: panel-common.yaml# >> + >> +properties: >> + compatible: >> + items: >> + - enum: >> + - sharp,ls026b3sa06 >> + - boe,vs026c4m-n52-6000 >> + - const: synaptics,r63455 >> + >> + reset-gpios: >> + maxItems: 2 >> + description: 2 reset pins for 2 physical panels >> + >> + left-pos-supply: >> + description: Positive 5.7V supply for left panel > > So, is the R63455 driving both panels or are there two panels, each > having R63455 controller? What if somebody gets a single Sharp panel and > wants to use it in their device? How will it match these bindings? It's highly improbable, those are very specialized panels that are designed for xr usage in pair. Yes a hobbyist could try to use a single panel but it's only usable when placed close to an eye, and barely useless if you don't have both eyes. Let's skip highly improbable use-cases and focus on the main use case of the hardware device. > >> + >> + right-pos-supply: >> + description: Positive 5.7V supply for right panel >> + >> + left-neg-supply: >> + description: Negative 5.7V supply for left panel >> + >> + right-neg-supply: >> + description: Negative 5.7V supply for right panel >> + >> + left-backlight-supply: >> + description: Backlight 21V supply for left panel >> + >> + right-backlight-supply: >> + description: Backlight 21V supply for right panel >> + >> + vdda-supply: >> + description: core 1.8V supply for panels >> + >> + ports: $ref: /schemas/graph.yaml#/properties/ports >> + >> +required: >> + - compatible >> + - reset-gpios >> + - left-pos-supply >> + - left-neg-supply >> + - right-pos-supply >> + - right-neg-supply >> + - left-backlight-supply >> + - right-backlight-supply >> + - vdda-supply >> + >> +additionalProperties: false >> + >> +examples: >> + - | >> + #include <dt-bindings/gpio/gpio.h> >> + >> + &mdss_dsi0 { > > Please drop the MDSS specifics, there should be one (or two) DSI busses, > driving your panels. The rests are details which are not necessary for > the example. > >> + vdda-supply = <&vreg_l3i_1p2>; >> + status = "okay"; >> + >> + qcom,dual-dsi-mode; >> + qcom,master-dsi; >> + >> + panel: panel@0 { >> + compatible = "sharp,ls026b3sa06", "synaptics,r63455"; >> + reg = <0>; >> + >> + reset-gpios = <&pm8550_gpios 3 GPIO_ACTIVE_HIGH>, >> + <&pm8550_gpios 11 GPIO_ACTIVE_HIGH>; >> + >> + left-pos-supply = <&vpos_left>; >> + left-neg-supply = <&vneg_left>; >> + right-pos-supply = <&vpos_right>; >> + right-neg-supply = <&vneg_right>; >> + left-backlight-supply = <&backlight_left>; >> + right-backlight-supply = <&backlight_right>; >> + >> + vdda-supply = <&vreg_l12b_1p8>; >> + >> + ports { >> + #address-cells = <1>; >> + #size-cells = <0>; >> + port@0 { >> + reg = <0>; >> + panel0_in: endpoint { >> + remote-endpoint = <&mdss_dsi0_out>; > > What is mdss_dsi0_out? > >> + }; >> + }; >> + >> + port@1 { >> + reg = <1>; >> + panel1_in: endpoint { >> + remote-endpoint = <&mdss_dsi1_out>; >> + }; >> + }; >> + }; >> + }; >> + >> + &mdss_dsi0_out { >> + remote-endpoint = <&panel0_in>; >> + data-lanes = <0 1 2>; >> + }; >> + >> + &mdss_dsi1_out { >> + remote-endpoint = <&panel1_in>; >> + data-lanes = <0 1 2>; >> + }; >> +... >> >> -- >> 2.43.0 >> > ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v4 4/5] dt-bindings: display: Add Synaptics R63455 panel support 2026-05-21 14:46 ` [PATCH v4 4/5] dt-bindings: display: Add Synaptics R63455 panel support Jun Nie ` (2 preceding siblings ...) 2026-05-21 20:24 ` Dmitry Baryshkov @ 2026-05-21 20:46 ` Rob Herring (Arm) 3 siblings, 0 replies; 15+ messages in thread From: Rob Herring (Arm) @ 2026-05-21 20:46 UTC (permalink / raw) To: Jun Nie Cc: Simona Vetter, Thomas Zimmermann, Krzysztof Kozlowski, Marijn Suijten, Neil Armstrong, linux-kernel, devicetree, linux-arm-msm, Dmitry Baryshkov, Rob Clark, Maxime Ripard, dri-devel, Maarten Lankhorst, Jessica Zhang, Conor Dooley, David Airlie, freedreno, Dmitry Baryshkov, Abhinav Kumar, Sean Paul On Thu, 21 May 2026 22:46:06 +0800, Jun Nie wrote: > Add support for the dual-panel system found in the virtual reality device. > This system consists of two physical 2160x2160 panels, each connected via > a MIPI DSI interface. The backlight is managed through DSI link. > > Signed-off-by: Jun Nie <jun.nie@linaro.org> > --- > .../bindings/display/panel/synaptics,r63455.yaml | 125 +++++++++++++++++++++ > 1 file changed, 125 insertions(+) > My bot found errors running 'make dt_binding_check' on your patch: yamllint warnings/errors: ./Documentation/devicetree/bindings/display/panel/synaptics,r63455.yaml:26:9: [warning] wrong indentation: expected 10 but found 8 (indentation) ./Documentation/devicetree/bindings/display/panel/synaptics,r63455.yaml:55:14: [error] syntax error: mapping values are not allowed here (syntax) dtschema/dtc warnings/errors: /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/display/panel/synaptics,r63455.yaml: ignoring, error parsing file ./Documentation/devicetree/bindings/display/panel/synaptics,r63455.yaml:55:14: mapping values are not allowed here make[2]: *** Deleting file 'Documentation/devicetree/bindings/display/panel/synaptics,r63455.example.dts' Documentation/devicetree/bindings/display/panel/synaptics,r63455.yaml:55:14: mapping values are not allowed here make[2]: *** [Documentation/devicetree/bindings/Makefile:26: Documentation/devicetree/bindings/display/panel/synaptics,r63455.example.dts] Error 1 make[2]: *** Waiting for unfinished jobs.... make[1]: *** [/builds/robherring/dt-review-ci/linux/Makefile:1659: dt_binding_check] Error 2 make: *** [Makefile:248: __sub-make] Error 2 doc reference errors (make refcheckdocs): See https://patchwork.kernel.org/project/devicetree/patch/20260521-sm8650-7-1-bonded-dsi-v4-4-a4dd5e0850f1@linaro.org The base for the series is generally the latest rc1. A different dependency should be noted in *this* patch. If you already ran 'make dt_binding_check' and didn't see the above error(s), then make sure 'yamllint' is installed and dt-schema is up to date: pip3 install dtschema --upgrade Please check and re-submit after running the above command yourself. Note that DT_SCHEMA_FILES can be set to your schema file to speed up checking your schema. However, it must be unset to test all examples with your schema. ^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v4 5/5] drm/panel: Add driver for Synaptics R63455 DSI panel 2026-05-21 14:46 [PATCH v4 0/5] Add support to 2 panels in bonded-DSI mode Jun Nie ` (3 preceding siblings ...) 2026-05-21 14:46 ` [PATCH v4 4/5] dt-bindings: display: Add Synaptics R63455 panel support Jun Nie @ 2026-05-21 14:46 ` Jun Nie 2026-05-21 16:30 ` sashiko-bot 4 siblings, 1 reply; 15+ messages in thread From: Jun Nie @ 2026-05-21 14:46 UTC (permalink / raw) To: Rob Clark, Dmitry Baryshkov, Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Sean Paul, Marijn Suijten, David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Neil Armstrong, Rob Herring, Krzysztof Kozlowski, Conor Dooley Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, devicetree, Jun Nie Add support for the DSI panels used in the virtual reality device. The device features two physical panels, each providing a MIPI DSI interface and a built-in LED backlight and expose a single logical panel to the DRM framework. Signed-off-by: Jun Nie <jun.nie@linaro.org> --- drivers/gpu/drm/panel/Kconfig | 9 + drivers/gpu/drm/panel/Makefile | 1 + drivers/gpu/drm/panel/panel-synaptics-r63455.c | 631 +++++++++++++++++++++++++ 3 files changed, 641 insertions(+) diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig index 7c2d9feb4064e..1ef3f51ec6593 100644 --- a/drivers/gpu/drm/panel/Kconfig +++ b/drivers/gpu/drm/panel/Kconfig @@ -1227,6 +1227,15 @@ config DRM_PANEL_SYNAPTICS_TDDI namesake, with varying resolutions and data lanes. They also have a built-in LED backlight and a touch controller. +config DRM_PANEL_SYNAPTICS_R63455 + tristate "Synaptics R63455-based panels" + depends on OF + depends on DRM_MIPI_DSI + depends on BACKLIGHT_CLASS_DEVICE + help + Say Y if you want to enable support for panels based on the + Synaptics R63455 controller. + config DRM_PANEL_TDO_TL070WSH30 tristate "TDO TL070WSH30 DSI panel" depends on OF diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile index dc8a05f2c34d9..ee6b41151804c 100644 --- a/drivers/gpu/drm/panel/Makefile +++ b/drivers/gpu/drm/panel/Makefile @@ -115,6 +115,7 @@ obj-$(CONFIG_DRM_PANEL_SITRONIX_ST7789V) += panel-sitronix-st7789v.o obj-$(CONFIG_DRM_PANEL_SUMMIT) += panel-summit.o obj-$(CONFIG_DRM_PANEL_SYNAPTICS_R63353) += panel-synaptics-r63353.o obj-$(CONFIG_DRM_PANEL_SYNAPTICS_TDDI) += panel-synaptics-tddi.o +obj-$(CONFIG_DRM_PANEL_SYNAPTICS_R63455) += panel-synaptics-r63455.o obj-$(CONFIG_DRM_PANEL_SONY_ACX565AKM) += panel-sony-acx565akm.o obj-$(CONFIG_DRM_PANEL_SONY_TD4353_JDI) += panel-sony-td4353-jdi.o obj-$(CONFIG_DRM_PANEL_SONY_TULIP_TRULY_NT35521) += panel-sony-tulip-truly-nt35521.o diff --git a/drivers/gpu/drm/panel/panel-synaptics-r63455.c b/drivers/gpu/drm/panel/panel-synaptics-r63455.c new file mode 100644 index 0000000000000..e429c28c7efc9 --- /dev/null +++ b/drivers/gpu/drm/panel/panel-synaptics-r63455.c @@ -0,0 +1,631 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2026, Linaro Ltd. 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/of_device.h> +#include <linux/of_graph.h> +#include <linux/pinctrl/consumer.h> +#include <linux/regulator/consumer.h> + +#include <video/mipi_display.h> + +#include <drm/display/drm_dsc.h> +#include <drm/display/drm_dsc_helper.h> +#include <drm/drm_mipi_dsi.h> +#include <drm/drm_modes.h> +#include <drm/drm_panel.h> +#include <drm/drm_print.h> +#include <drm/drm_probe_helper.h> + +#define R63455_MF_CMD_ACCESS_PROTECT 0xb0 +#define R63455_SEQ_CTL 0xd6 +#define R63455_DSI_CTL 0xb6 +#define R63455_DISP_MODE 0xb7 +#define R63455_GEN_OUTPIN_SET 0xb9 +#define R63455_DISP_SET1 0xc0 +#define R63455_DISP_SET2 0xf1 +#define R63455_DISP_SET3 0xc6 +#define R63455_DISP_SET3_2 0xcd +#define R63455_DISP_SET4 0xcf +#define R63455_DISP_SET5 0xec +#define R63455_DISP_SET6 0xef +#define R63455_TE_GPIO_CTL 0xbe +#define R63455_PPS_SET 0xe6 + +#define BRIGHTNESS_DEFAULT 256 +#define BRIGHTNESS_MAX_120 367 + +#define VBP 100 +#define VFP 700 +#define VID_VS_DELAY 1112 +#define GPO1_TES1 4068 +#define RTN 59 + +static const char * const vdda_driver[] = { + "vdda", +}; + +static const char * const dual_backlight_driver[] = { + "left-backlight", + "right-backlight", +}; + +static const char * const dual_lcd_bias_pos[] = { + "left-pos", + "right-pos", +}; + +static const char * const dual_lcd_bias_neg[] = { + "left-neg", + "right-neg" +}; + +struct r63455_ctx { + struct device *dev; + struct drm_panel panel; + + struct regulator_bulk_data reg_vdda[ARRAY_SIZE(vdda_driver)]; + struct regulator_bulk_data reg_bl[ARRAY_SIZE(dual_backlight_driver)]; + struct regulator_bulk_data reg_lcd_bias_pos[ARRAY_SIZE(dual_lcd_bias_pos)]; + struct regulator_bulk_data reg_lcd_bias_neg[ARRAY_SIZE(dual_lcd_bias_neg)]; + + struct gpio_descs *reset_gpios; + int (*dsi_init_seq)(struct drm_panel *panel); + struct backlight_device *backlight; + struct mipi_dsi_device *dsi[2]; + struct drm_dsc_config dsc_cfg; +}; + +static inline struct r63455_ctx *panel_to_ctx(struct drm_panel *panel) +{ + return container_of(panel, struct r63455_ctx, panel); +} + +static const struct drm_display_mode modes = { + .name = "4320x2160_120", + .clock = (2160 + 24 + 20 + 20) * (2160 + 404 + 1 + 20) * 120 * 2 / 1000, + .hdisplay = 2160 * 2, + .hsync_start = (2160 + 24) * 2, + .hsync_end = (2160 + 24 + 20) * 2, + .htotal = (2160 + 24 + 20 + 20) * 2, + .vdisplay = 2160, + .vsync_start = 2160 + 404, + .vsync_end = 2160 + 404 + 1, + .vtotal = 2160 + 404 + 1 + 20, + .width_mm = 50 * 2, + .height_mm = 50, + .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, +}; + +#define r63455_dsi_write_seq(ctx, dsi_ctx, cmd, seq...) \ + do { \ + u8 d[] = {cmd, seq}; \ + dsi_ctx.dsi = ctx->dsi[0]; \ + mipi_dsi_dcs_write_buffer_multi(&dsi_ctx, d, ARRAY_SIZE(d)); \ + dsi_ctx.dsi = ctx->dsi[1]; \ + mipi_dsi_dcs_write_buffer_multi(&dsi_ctx, d, ARRAY_SIZE(d)); \ + } while (0) + +#define r63455_dsi_write_buffer(ctx, dsi_ctx, d) \ + do { \ + dsi_ctx.dsi = ctx->dsi[0]; \ + mipi_dsi_dcs_write_buffer_multi(&dsi_ctx, d, ARRAY_SIZE(d)); \ + dsi_ctx.dsi = ctx->dsi[1]; \ + mipi_dsi_dcs_write_buffer_multi(&dsi_ctx, d, ARRAY_SIZE(d)); \ + } while (0) + +#define LE16_BYTE0(val) (le16_to_cpu(val) & 0xff) +#define LE16_BYTE1(val) ((le16_to_cpu(val) >> 8) & 0xff) +#define BE16_BYTE0(val) (be16_to_cpu(val) & 0xff) +#define BE16_BYTE1(val) ((be16_to_cpu(val) >> 8) & 0xff) + +static int r63455_dsi_populate_dsc_params(struct r63455_ctx *ctx) +{ + int ret; + struct drm_dsc_config *dsc = &ctx->dsc_cfg; + + dsc->simple_422 = 0; + dsc->convert_rgb = 1; + dsc->vbr_enable = 0; + + drm_dsc_set_const_params(dsc); + drm_dsc_set_rc_buf_thresh(dsc); + + /* handle only bpp = bpc = 8, pre-SCR panels */ + ret = drm_dsc_setup_rc_params(dsc, DRM_DSC_1_1_PRE_SCR); + if (ret < 0) + DRM_DEV_ERROR(ctx->dev, "failed to setup dsc params\n"); + + dsc->initial_scale_value = drm_dsc_initial_scale_value(dsc); + dsc->line_buf_depth = dsc->bits_per_component + 1; + + return drm_dsc_compute_rc_parameters(dsc); +} + +static int r63455_init_dsc_config(struct r63455_ctx *ctx) +{ + ctx->dsc_cfg = (struct drm_dsc_config) { + .dsc_version_major = 0x1, + .dsc_version_minor = 0x2, + .dsc_slice_per_pkt = 4, + .slice_height = 48, + .slice_width = 540, + .slice_count = 4, + .bits_per_component = 8, + .bits_per_pixel = 8 << 4, + .block_pred_enable = true, + + .pic_width = 2160, + .pic_height = 2160, + }; + + return r63455_dsi_populate_dsc_params(ctx); +} + +static int r63455_panel_on_sharp_ls026b3sa06(struct drm_panel *panel) +{ + struct r63455_ctx *ctx = panel_to_ctx(panel); + struct mipi_dsi_multi_context dsi_ctx = { 0 }; + + u8 pps_cmd[1 + sizeof(struct drm_dsc_picture_parameter_set)]; + + drm_dsc_pps_payload_pack((void *)&pps_cmd[1], &ctx->dsc_cfg); + pps_cmd[0] = R63455_PPS_SET; + + r63455_dsi_write_seq(ctx, dsi_ctx, R63455_MF_CMD_ACCESS_PROTECT, 0x00); + r63455_dsi_write_seq(ctx, dsi_ctx, R63455_SEQ_CTL, 0x00); + r63455_dsi_write_seq(ctx, dsi_ctx, + R63455_DSI_CTL, + 0x20, 0x6b, 0x80, 0x06, 0x33, 0x9a, 0x00, 0x1a, + 0x7a); + r63455_dsi_write_seq(ctx, dsi_ctx, R63455_DISP_MODE, + 0x54, 0x00, 0x00, 0x00); + r63455_dsi_write_seq(ctx, dsi_ctx, R63455_GEN_OUTPIN_SET, + 0xf, 0xe4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xf, 0xb2, 0x00, 0x64); + r63455_dsi_write_seq(ctx, dsi_ctx, R63455_DISP_SET3, + 0x08, 0x70, 0x28, 0x48, 0x00, 0x00, 0x13, 0x21, + 0xff, 0x00, 0x0f, 0x01, 0x14, 0x17, 0x00, 0x00, + 0x00, 0x02, 0x40, 0x0C, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x70, 0x08, + 0xD0, 0x02, 0x21, 0x6F, 0x08, 0x5A, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00); + r63455_dsi_write_seq(ctx, dsi_ctx, R63455_DISP_SET1, + RTN, 0x86, LE16_BYTE0(VBP), LE16_BYTE1(VBP), 0x08, + 0x70, BE16_BYTE0(VFP), BE16_BYTE1(VFP), 0x00, + 0x00, 0x08, 0x3B, 0x00, 0x00, 0x19, 0x01, 0x22); + r63455_dsi_write_seq(ctx, dsi_ctx, R63455_DISP_SET3_2, 0x00); + r63455_dsi_write_seq(ctx, dsi_ctx, R63455_DISP_SET4, + 0x8b, 0x00, 0x80, 0x46, 0x61, 0x00, 0x8b); + r63455_dsi_write_seq(ctx, dsi_ctx, R63455_DISP_SET5, + BE16_BYTE0(VID_VS_DELAY), + BE16_BYTE1(VID_VS_DELAY), + 0x00, 0x00, 0x00); + r63455_dsi_write_seq(ctx, dsi_ctx, R63455_DISP_SET6, + 0x00, 0x24, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0A, 0x0A, 0x00, 0x00, 0x00, 0x03, + 0x1D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00); + r63455_dsi_write_seq(ctx, dsi_ctx, R63455_TE_GPIO_CTL, + 0x00, 0x6A, 0x02); + r63455_dsi_write_buffer(ctx, dsi_ctx, pps_cmd); + r63455_dsi_write_seq(ctx, dsi_ctx, MIPI_DCS_SET_TEAR_ON, 0x00); + r63455_dsi_write_seq(ctx, dsi_ctx, MIPI_DCS_SET_ADDRESS_MODE, 0x40); + r63455_dsi_write_seq(ctx, dsi_ctx, MIPI_DCS_EXIT_SLEEP_MODE); + mipi_dsi_msleep(&dsi_ctx, 170); + r63455_dsi_write_seq(ctx, dsi_ctx, MIPI_DCS_SET_DISPLAY_ON); + mipi_dsi_msleep(&dsi_ctx, 200); + + return dsi_ctx.accum_err; +} + +static int r63455_panel_on_boe_vs026c4m_n52_26000(struct drm_panel *panel) +{ + struct r63455_ctx *ctx = panel_to_ctx(panel); + struct mipi_dsi_multi_context dsi_ctx = { 0 }; + + u8 pps_cmd[1 + sizeof(struct drm_dsc_picture_parameter_set)]; + + drm_dsc_pps_payload_pack((void *)&pps_cmd[1], &ctx->dsc_cfg); + pps_cmd[0] = R63455_PPS_SET; + + r63455_dsi_write_seq(ctx, dsi_ctx, + R63455_MF_CMD_ACCESS_PROTECT, 0x00); + r63455_dsi_write_seq(ctx, dsi_ctx, R63455_SEQ_CTL, 0x00); + r63455_dsi_write_seq(ctx, dsi_ctx, R63455_DSI_CTL, + 0x20, 0x6b, 0x80, 0x06, 0x33, 0x9A, 0x00, + 0x1a, 0x7a); + r63455_dsi_write_seq(ctx, dsi_ctx, R63455_DISP_MODE, + 0x54, 0x00, 0x00, 0x00); + r63455_dsi_write_seq(ctx, dsi_ctx, R63455_GEN_OUTPIN_SET, + 0xf, 0xe4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xf, 0xb2, + 0xf, 0xb2, 0x00, 0x64); + r63455_dsi_write_seq(ctx, dsi_ctx, R63455_DISP_SET3, + 0x0B, 0x70, 0x08, 0x48, 0x00, 0x00, 0x13, 0x01, + 0xFF, 0x00, 0x01, 0x09, 0x16, 0x16, 0x00, 0x00, + 0x00, 0x01, 0x40, 0x0C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x70, 0x08, + 0xD0, 0x02, 0x21, 0x6F, 0x08, 0x5A, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + r63455_dsi_write_seq(ctx, dsi_ctx, R63455_DISP_SET1, + RTN, 0x86, LE16_BYTE0(VBP), LE16_BYTE1(VBP), 0x08, + 0x70, BE16_BYTE0(VFP), BE16_BYTE1(VFP), 0x00, + 0x00, 0x08, 0x3A, 0x00, 0x00, 0x17, 0x00, 0x17); + r63455_dsi_write_seq(ctx, dsi_ctx, R63455_DISP_SET3_2, 0x00); + r63455_dsi_write_seq(ctx, dsi_ctx, R63455_DISP_SET4, + 0x8b, 0x00, 0x80, 0x46, 0x61, 0x00, 0x8b); + r63455_dsi_write_seq(ctx, dsi_ctx, R63455_DISP_SET5, + BE16_BYTE0(VID_VS_DELAY), BE16_BYTE1(VID_VS_DELAY), + 0x00, 0x00, 0x00); + r63455_dsi_write_seq(ctx, dsi_ctx, + R63455_TE_GPIO_CTL, 0x00, 0x6A, 0x02); + r63455_dsi_write_buffer(ctx, dsi_ctx, pps_cmd); + r63455_dsi_write_seq(ctx, dsi_ctx, MIPI_DCS_SET_TEAR_ON, 0x00); + r63455_dsi_write_seq(ctx, dsi_ctx, MIPI_DCS_EXIT_SLEEP_MODE); + mipi_dsi_msleep(&dsi_ctx, 170); + r63455_dsi_write_seq(ctx, dsi_ctx, MIPI_DCS_SET_DISPLAY_ON); + mipi_dsi_msleep(&dsi_ctx, 200); + + return dsi_ctx.accum_err; +} + +static int r63455_set_brightness(struct r63455_ctx *ctx, u16 brightness, + u16 pulse_offset_rows) +{ + struct mipi_dsi_multi_context dsi_ctx = { 0 }; + u16 gpo1_tew1; + + gpo1_tew1 = brightness > BRIGHTNESS_MAX_120 ? + BRIGHTNESS_MAX_120 : brightness; + + ctx->dsi[0]->mode_flags &= ~MIPI_DSI_MODE_LPM; + ctx->dsi[1]->mode_flags &= ~MIPI_DSI_MODE_LPM; + + r63455_dsi_write_seq(ctx, dsi_ctx, + R63455_GEN_OUTPIN_SET, + 0x0f, 0xe4, + BE16_BYTE0(gpo1_tew1), + BE16_BYTE1(gpo1_tew1), + 0x00, 0x00, 0x00, 0x00, 0x0f, 0xb2, + BE16_BYTE0(brightness), + BE16_BYTE1(brightness)); + + ctx->dsi[0]->mode_flags |= MIPI_DSI_MODE_LPM; + ctx->dsi[1]->mode_flags |= MIPI_DSI_MODE_LPM; + + return dsi_ctx.accum_err; +} + +static int r63455_disable(struct drm_panel *panel) +{ + struct r63455_ctx *ctx = panel_to_ctx(panel); + struct mipi_dsi_multi_context dsi_ctx = { 0 }; + + ctx->dsi[0]->mode_flags &= ~MIPI_DSI_MODE_LPM; + ctx->dsi[1]->mode_flags &= ~MIPI_DSI_MODE_LPM; + + r63455_dsi_write_seq(ctx, dsi_ctx, MIPI_DCS_SET_DISPLAY_OFF); + r63455_dsi_write_seq(ctx, dsi_ctx, MIPI_DCS_SET_TEAR_OFF); + r63455_dsi_write_seq(ctx, dsi_ctx, MIPI_DCS_ENTER_SLEEP_MODE); + + mipi_dsi_msleep(&dsi_ctx, 200); + + if (dsi_ctx.accum_err) + return dsi_ctx.accum_err; + + return backlight_disable(ctx->backlight); +} + +static int r63455_unprepare(struct drm_panel *panel) +{ + struct r63455_ctx *ctx = panel_to_ctx(panel); + int ret; + + gpiod_set_value(ctx->reset_gpios->desc[0], 0); + gpiod_set_value(ctx->reset_gpios->desc[1], 0); + + msleep(25); + ret = regulator_bulk_disable(ARRAY_SIZE(ctx->reg_lcd_bias_neg), + ctx->reg_lcd_bias_neg); + if (ret) + dev_err(ctx->dev, "Could not disable bias negative\n"); + + usleep_range(1000, 2000); + ret = regulator_bulk_disable(ARRAY_SIZE(ctx->reg_lcd_bias_pos), + ctx->reg_lcd_bias_pos); + if (ret) + dev_err(ctx->dev, "Could not disable bias positive\n"); + + msleep(20); + + ret = regulator_bulk_disable(ARRAY_SIZE(ctx->reg_vdda), ctx->reg_vdda); + if (ret) + dev_err(ctx->dev, "Could not disable vdda\n"); + + ret = regulator_bulk_disable(ARRAY_SIZE(ctx->reg_bl), ctx->reg_bl); + if (ret) + dev_err(ctx->dev, + "failed to disable regulator backlight: %d\n", ret); + + return ret; +} + +static int r63455_enable(struct drm_panel *panel) +{ + struct r63455_ctx *ctx = panel_to_ctx(panel); + int ret; + + ctx->dsi[0]->mode_flags |= MIPI_DSI_MODE_LPM; + ctx->dsi[1]->mode_flags |= MIPI_DSI_MODE_LPM; + + msleep(20); + ret = ctx->dsi_init_seq(panel); + if (ret < 0) { + DRM_DEV_ERROR(ctx->dev, "dsi init failed\n"); + return ret; + } + ctx->backlight->props.pulse_offset_rows = GPO1_TES1; + + ret = backlight_enable(ctx->backlight); + if (ret < 0) { + DRM_DEV_ERROR(ctx->dev, "failed to enable backlight\n"); + return ret; + } + + return ret; +} + +static int r63455_prepare(struct drm_panel *panel) +{ + struct r63455_ctx *ctx = panel_to_ctx(panel); + int ret; + + ret = regulator_bulk_enable(ARRAY_SIZE(ctx->reg_bl), ctx->reg_bl); + if (ret) { + dev_err(ctx->dev, "Could not enable backlight\n"); + return ret; + } + + ret = regulator_bulk_enable(ARRAY_SIZE(ctx->reg_vdda), ctx->reg_vdda); + if (ret) { + dev_err(ctx->dev, "Could not enable vdda\n"); + goto bl_off; + } + + usleep_range(1000, 2000); + ret = regulator_bulk_enable(ARRAY_SIZE(ctx->reg_lcd_bias_pos), + ctx->reg_lcd_bias_pos); + if (ret) { + dev_err(ctx->dev, "Could not enable bias positive\n"); + goto vdda_off; + } + usleep_range(1000, 2000); + ret = regulator_bulk_enable(ARRAY_SIZE(ctx->reg_lcd_bias_neg), + ctx->reg_lcd_bias_neg); + if (ret) { + dev_err(ctx->dev, "Could not enable bias negative\n"); + goto bias_off; + } + + msleep(20); + gpiod_set_value(ctx->reset_gpios->desc[0], 1); + gpiod_set_value(ctx->reset_gpios->desc[1], 1); + + return 0; + +bl_off: + regulator_bulk_disable(ARRAY_SIZE(ctx->reg_bl), ctx->reg_bl); +vdda_off: + regulator_bulk_disable(ARRAY_SIZE(ctx->reg_vdda), ctx->reg_vdda); +bias_off: + regulator_bulk_disable(ARRAY_SIZE(ctx->reg_lcd_bias_pos), + ctx->reg_lcd_bias_pos); + return ret; +} + +static int r63455_bl_update_status(struct backlight_device *bl) +{ + struct mipi_dsi_device *dsi = bl_get_data(bl); + struct r63455_ctx *r63455_ctx = mipi_dsi_get_drvdata(dsi); + + return r63455_set_brightness(r63455_ctx, bl->props.brightness, + bl->props.pulse_offset_rows); +} + +static const struct backlight_ops r63455_bl_ops = { + .update_status = r63455_bl_update_status, +}; + +static int r63455_get_modes(struct drm_panel *panel, + struct drm_connector *connector) +{ + return drm_connector_helper_get_modes_fixed(connector, &modes); +} + +static const struct drm_panel_funcs r63455_drm_funcs = { + .disable = r63455_disable, + .enable = r63455_enable, + .unprepare = r63455_unprepare, + .prepare = r63455_prepare, + .get_modes = r63455_get_modes, +}; + +static int r63455_panel_add(struct r63455_ctx *ctx) +{ + struct device *dev = ctx->dev; + struct backlight_properties bl_props; + int ret, i; + + for (i = 0; i < ARRAY_SIZE(ctx->reg_vdda); i++) + ctx->reg_vdda[i].supply = vdda_driver[i]; + + ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->reg_vdda), + ctx->reg_vdda); + if (ret < 0) + return ret; + + for (i = 0; i < ARRAY_SIZE(dual_backlight_driver); i++) + ctx->reg_bl[i].supply = dual_backlight_driver[i]; + + ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->reg_bl), + ctx->reg_bl); + if (ret < 0) + return ret; + + for (i = 0; i < ARRAY_SIZE(ctx->reg_lcd_bias_pos); i++) + ctx->reg_lcd_bias_pos[i].supply = dual_lcd_bias_pos[i]; + + ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->reg_lcd_bias_pos), + ctx->reg_lcd_bias_pos); + if (ret < 0) + return ret; + + for (i = 0; i < ARRAY_SIZE(ctx->reg_lcd_bias_neg); i++) + ctx->reg_lcd_bias_neg[i].supply = dual_lcd_bias_neg[i]; + + ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->reg_lcd_bias_neg), + ctx->reg_lcd_bias_neg); + if (ret < 0) + return ret; + + ctx->reset_gpios = devm_gpiod_get_array(dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(ctx->reset_gpios)) + return PTR_ERR(ctx->reset_gpios); + + memset(&bl_props, 0, sizeof(bl_props)); + bl_props.type = BACKLIGHT_RAW; + bl_props.brightness = BRIGHTNESS_DEFAULT; + bl_props.max_brightness = BRIGHTNESS_MAX_120; + + ctx->backlight = devm_backlight_device_register(dev, dev_name(dev), + dev, ctx->dsi[0], + &r63455_bl_ops, + &bl_props); + if (IS_ERR(ctx->backlight)) { + ret = PTR_ERR(ctx->backlight); + dev_err(dev, "Failed to register backlight (%d)\n", ret); + return ret; + } + + ctx->panel.prepare_prev_first = true; + return devm_drm_panel_add(dev, &ctx->panel); +} + +static int r63455_probe(struct mipi_dsi_device *dsi) +{ + struct device *dev = &dsi->dev; + struct r63455_ctx *ctx; + struct mipi_dsi_device *dsi1_device; + struct device_node *dsi1; + struct mipi_dsi_host *dsi1_host; + struct mipi_dsi_device *dsi_dev; + int ret = 0; + int i; + + const struct mipi_dsi_device_info info = { + .type = "r63455-dsi-panel", + .channel = 0, + .node = NULL, + }; + + ctx = devm_drm_panel_alloc(&dsi->dev, __typeof(*ctx), panel, + &r63455_drm_funcs, DRM_MODE_CONNECTOR_DSI); + + ctx->dsi_init_seq = of_device_get_match_data(dev); + if (!ctx->dsi_init_seq) + return -ENODEV; + + dsi1 = of_graph_get_remote_node(dsi->dev.of_node, 1, -1); + if (!dsi1) { + DRM_DEV_ERROR(dev, "failed to get secondary dsi\n"); + return -ENODEV; + } + + dsi1_host = of_find_mipi_dsi_host_by_node(dsi1); + of_node_put(dsi1); + if (!dsi1_host) { + DRM_DEV_ERROR(dev, "failed to find secondary dsi host\n"); + return -EPROBE_DEFER; + } + + dsi1_device = mipi_dsi_device_register_full(dsi1_host, &info); + if (IS_ERR(dsi1_device)) { + DRM_DEV_ERROR(dev, "failed to create dsi device\n"); + return PTR_ERR(dsi1_device); + } + + ctx->dsi[1] = dsi1_device; + mipi_dsi_set_drvdata(dsi, ctx); + ctx->dev = dev; + ctx->dsi[0] = dsi; + + ret = r63455_init_dsc_config(ctx); + if (ret) + return ret; + + ctx->dsi[0]->dsc = &ctx->dsc_cfg; + ctx->dsi[0]->dual_panel = true; + ctx->dsi[1]->dual_panel = true; + ctx->dsi[1]->dsc = &ctx->dsc_cfg; + + ret = r63455_panel_add(ctx); + if (ret) { + DRM_DEV_ERROR(dev, "failed to add panel %d\n", ret); + return ret; + } + + for (i = 0; i < 2; i++) { + dsi_dev = ctx->dsi[i]; + dsi_dev->lanes = 3; + dsi_dev->format = MIPI_DSI_FMT_RGB888; + dsi_dev->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_LPM | + MIPI_DSI_CLOCK_NON_CONTINUOUS; + ret = devm_mipi_dsi_attach(dev, dsi_dev); + if (ret < 0) { + DRM_DEV_ERROR(dev, "dsi attach failed i = %d\n", i); + return ret; + } + } + + return 0; +} + +static const struct of_device_id r63455_of_match[] = { + { + .compatible = "sharp,ls026b3sa06", + .data = r63455_panel_on_sharp_ls026b3sa06, + }, + { + .compatible = "boe,vs026c4m-n52-6000", + .data = r63455_panel_on_boe_vs026c4m_n52_26000, + }, + { } +}; +MODULE_DEVICE_TABLE(of, r63455_of_match); + +static struct mipi_dsi_driver r63455_driver = { + .driver = { + .name = "panel-synaptics-r63455", + .of_match_table = r63455_of_match, + }, + .probe = r63455_probe, +}; +module_mipi_dsi_driver(r63455_driver); + +MODULE_DESCRIPTION("Synaptics R63455 DSI Panel Driver"); +MODULE_LICENSE("GPL"); -- 2.43.0 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH v4 5/5] drm/panel: Add driver for Synaptics R63455 DSI panel 2026-05-21 14:46 ` [PATCH v4 5/5] drm/panel: Add driver for Synaptics R63455 DSI panel Jun Nie @ 2026-05-21 16:30 ` sashiko-bot 0 siblings, 0 replies; 15+ messages in thread From: sashiko-bot @ 2026-05-21 16:30 UTC (permalink / raw) To: Jun Nie; +Cc: robh, conor+dt, devicetree Thank you for your contribution! Sashiko AI review found 10 potential issue(s) to consider: - [High] Incorrect order of error unwinding labels in `r63455_prepare` causes resource leaks and unbalanced regulator operations. - [High] The secondary DSI device registered during probe is never unregistered, causing a memory and device leak. - [High] Endianness extraction macros misuse host-endian functions, resulting in reversed byte order on Big Endian architectures. - [High] Unconditional access to `ctx->reset_gpios->desc[1]` leads to an out-of-bounds array read if only one reset GPIO is provided. - [High] Failure of `drm_dsc_setup_rc_params` is logged but ignored, leading to division by zero and uninitialized data usage. - [High] Backlight updates send DSI commands after the panel has entered sleep mode, risking hardware timeouts. - [High] Premature publication of backlight and panel interfaces leads to use-before-initialization races. - [High] Unprotected concurrent read-modify-write on `mode_flags` causes data races. - [High] Unaligned pointer cast causes unaligned memory access when packing DSC PPS payload. - [Low] Missing Kconfig dependencies for DRM DSC helpers causes build failures. -- commit b5b6e09241eeff17cb03a31aac27b70f4e5ca911 Author: Jun Nie <jun.nie@linaro.org> Subject: drm/panel: Add driver for Synaptics R63455 DSI panel This commit adds support for the DSI panels used in the virtual reality device. The device features two physical panels, each providing a MIPI DSI interface and a built-in LED backlight, and exposes a single logical panel to the DRM framework. > diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig > --- a/drivers/gpu/drm/panel/Kconfig > +++ b/drivers/gpu/drm/panel/Kconfig [ ... ] > @@ -1185,6 +1185,15 @@ config DRM_PANEL_SYNAPTICS_TDDI > namesake, with varying resolutions and data lanes. They also have a > built-in LED backlight and a touch controller. > > +config DRM_PANEL_SYNAPTICS_R63455 > + tristate "Synaptics R63455-based panels" > + depends on OF > + depends on DRM_MIPI_DSI > + depends on BACKLIGHT_CLASS_DEVICE > + help > + Say Y if you want to enable support for panels based on the > + Synaptics R63455 controller. [Severity: Low] Does this need to select DRM_DISPLAY_DSC_HELPER or DRM_DISPLAY_HELPER? The driver calls drm_dsc_set_const_params and other DSC helpers, which might cause link-time failures if the helper infrastructure is not built. [ ... ] > diff --git a/drivers/gpu/drm/panel/panel-synaptics-r63455.c b/drivers/gpu/drm/panel/panel-synaptics-r63455.c > --- /dev/null > +++ b/drivers/gpu/drm/panel/panel-synaptics-r63455.c [ ... ] > +#define r63455_dsi_write_buffer(ctx, dsi_ctx, d) \ > + do { \ > + dsi_ctx.dsi = ctx->dsi[0]; \ > + mipi_dsi_dcs_write_buffer_multi(&dsi_ctx, d, ARRAY_SIZE(d)); \ > + dsi_ctx.dsi = ctx->dsi[1]; \ > + mipi_dsi_dcs_write_buffer_multi(&dsi_ctx, d, ARRAY_SIZE(d)); \ > + } while (0) > + > +#define LE16_BYTE0(val) (le16_to_cpu(val) & 0xff) > +#define LE16_BYTE1(val) ((le16_to_cpu(val) >> 8) & 0xff) [Severity: High] Are these macros extracting the correct bytes on big endian architectures? Using le16_to_cpu() on a native integer constant swaps the bytes on big endian systems. Applying the bitwise operations afterward will extract the most significant byte instead of the least significant byte. Would standard bitwise shifts be safer here? [ ... ] > +static int r63455_dsi_populate_dsc_params(struct r63455_ctx *ctx) > +{ > + int ret; > + struct drm_dsc_config *dsc = &ctx->dsc_cfg; [ ... ] > + /* handle only bpp = bpc = 8, pre-SCR panels */ > + ret = drm_dsc_setup_rc_params(dsc, DRM_DSC_1_1_PRE_SCR); > + if (ret < 0) > + DRM_DEV_ERROR(ctx->dev, "failed to setup dsc params\n"); > + > + dsc->initial_scale_value = drm_dsc_initial_scale_value(dsc); [Severity: High] Should this return early if drm_dsc_setup_rc_params() fails? If execution continues, the driver will use uninitialized DSC configuration parameters. Because values like initial_xmit_delay might remain zero, it can result in a division by zero when calculating final_scale inside drm_dsc_compute_rc_parameters(). > + dsc->line_buf_depth = dsc->bits_per_component + 1; > + > + return drm_dsc_compute_rc_parameters(dsc); > +} [ ... ] > +static int r63455_panel_on_sharp_ls026b3sa06(struct drm_panel *panel) > +{ > + struct r63455_ctx *ctx = panel_to_ctx(panel); > + struct mipi_dsi_multi_context dsi_ctx = { 0 }; > + > + u8 pps_cmd[1 + sizeof(struct drm_dsc_picture_parameter_set)]; > + > + drm_dsc_pps_payload_pack((void *)&pps_cmd[1], &ctx->dsc_cfg); [Severity: High] Can this unaligned pointer cause alignment faults? Passing &pps_cmd[1] forces the base address to be odd. Since drm_dsc_pps_payload_pack() treats the pointer as a struct and performs 16-bit stores to its fields, this might trigger alignment panics on architectures that strictly enforce memory alignment. [ ... ] > +static int r63455_set_brightness(struct r63455_ctx *ctx, u16 brightness, > + u16 pulse_offset_rows) > +{ > + struct mipi_dsi_multi_context dsi_ctx = { 0 }; > + u16 gpo1_tew1; > + > + gpo1_tew1 = brightness > BRIGHTNESS_MAX_120 ? > + BRIGHTNESS_MAX_120 : brightness; > + > + ctx->dsi[0]->mode_flags &= ~MIPI_DSI_MODE_LPM; [Severity: High] Can this read-modify-write of mode_flags race with the similar modifications in r63455_enable() and r63455_disable()? Because set_brightness() is called from sysfs context and enable/disable from DRM commit context, concurrent access might corrupt mode_flags and drop critical settings like MIPI_DSI_MODE_VIDEO. > + ctx->dsi[1]->mode_flags &= ~MIPI_DSI_MODE_LPM; [ ... ] > +static int r63455_disable(struct drm_panel *panel) > +{ > + struct r63455_ctx *ctx = panel_to_ctx(panel); > + struct mipi_dsi_multi_context dsi_ctx = { 0 }; > + > + ctx->dsi[0]->mode_flags &= ~MIPI_DSI_MODE_LPM; > + ctx->dsi[1]->mode_flags &= ~MIPI_DSI_MODE_LPM; > + > + r63455_dsi_write_seq(ctx, dsi_ctx, MIPI_DCS_SET_DISPLAY_OFF); > + r63455_dsi_write_seq(ctx, dsi_ctx, MIPI_DCS_SET_TEAR_OFF); > + r63455_dsi_write_seq(ctx, dsi_ctx, MIPI_DCS_ENTER_SLEEP_MODE); > + > + mipi_dsi_msleep(&dsi_ctx, 200); > + > + if (dsi_ctx.accum_err) > + return dsi_ctx.accum_err; > + > + return backlight_disable(ctx->backlight); [Severity: High] Is it safe to disable the backlight here? The backlight_disable() function calls r63455_set_brightness(), which will send DSI configuration commands to the panel. Doing so after sending MIPI_DCS_ENTER_SLEEP_MODE violates the DSI hardware contracts and might cause bus timeouts or hardware crashes. > +} > + > +static int r63455_unprepare(struct drm_panel *panel) > +{ > + struct r63455_ctx *ctx = panel_to_ctx(panel); > + int ret; > + > + gpiod_set_value(ctx->reset_gpios->desc[0], 0); > + gpiod_set_value(ctx->reset_gpios->desc[1], 0); [Severity: High] What happens if the device tree only provides a single reset GPIO? If ndescs is 1, accessing desc[1] will read past the end of the flexible array, resulting in a garbage pointer dereference. [ ... ] > +static int r63455_prepare(struct drm_panel *panel) > +{ > + struct r63455_ctx *ctx = panel_to_ctx(panel); > + int ret; [ ... ] > + msleep(20); > + gpiod_set_value(ctx->reset_gpios->desc[0], 1); > + gpiod_set_value(ctx->reset_gpios->desc[1], 1); > + > + return 0; > + > +bl_off: > + regulator_bulk_disable(ARRAY_SIZE(ctx->reg_bl), ctx->reg_bl); > +vdda_off: > + regulator_bulk_disable(ARRAY_SIZE(ctx->reg_vdda), ctx->reg_vdda); > +bias_off: > + regulator_bulk_disable(ARRAY_SIZE(ctx->reg_lcd_bias_pos), > + ctx->reg_lcd_bias_pos); > + return ret; [Severity: High] Are these error labels in the correct order? They appear to fall through sequentially rather than unwinding in reverse. If reg_vdda fails to enable, the jump to bl_off will disable the backlight, but then incorrectly fall through to vdda_off and bias_off. This causes regulators that were never enabled to be disabled, and completely skips disabling regulators that were actually enabled. > +} [ ... ] > +static int r63455_probe(struct mipi_dsi_device *dsi) > +{ > + struct device *dev = &dsi->dev; > + struct r63455_ctx *ctx; > + struct mipi_dsi_device *dsi1_device; [ ... ] > + dsi1_host = of_find_mipi_dsi_host_by_node(dsi1); > + of_node_put(dsi1); > + if (!dsi1_host) { > + DRM_DEV_ERROR(dev, "failed to find secondary dsi host\n"); > + return -EPROBE_DEFER; > + } > + > + dsi1_device = mipi_dsi_device_register_full(dsi1_host, &info); [Severity: High] Does this dynamically allocated dsi1_device need to be unregistered? There is no call to mipi_dsi_device_unregister() in the error paths below or in a remove callback for the driver, which could cause a permanent device and memory leak when the module is unloaded or fails to probe. > + if (IS_ERR(dsi1_device)) { > + DRM_DEV_ERROR(dev, "failed to create dsi device\n"); > + return PTR_ERR(dsi1_device); > + } [ ... ] > + ret = r63455_panel_add(ctx); > + if (ret) { > + DRM_DEV_ERROR(dev, "failed to add panel %d\n", ret); > + return ret; > + } > + > + for (i = 0; i < 2; i++) { > + dsi_dev = ctx->dsi[i]; > + dsi_dev->lanes = 3; > + dsi_dev->format = MIPI_DSI_FMT_RGB888; > + dsi_dev->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_LPM | > + MIPI_DSI_CLOCK_NON_CONTINUOUS; > + ret = devm_mipi_dsi_attach(dev, dsi_dev); [Severity: High] Does calling r63455_panel_add() before devm_mipi_dsi_attach() expose the backlight sysfs interface too early? If userspace writes to the brightness node before the DSI lanes and formats are configured and attached, it could trigger a DSI transfer on an unattached device and crash the system. > + if (ret < 0) { > + DRM_DEV_ERROR(dev, "dsi attach failed i = %d\n", i); > + return ret; > + } > + } > + > + return 0; > +} -- Sashiko AI review · https://sashiko.dev/#/patchset/20260521-sm8650-7-1-bonded-dsi-v4-0-a4dd5e0850f1@linaro.org?part=5 ^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2026-05-22 6:32 UTC | newest] Thread overview: 15+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-05-21 14:46 [PATCH v4 0/5] Add support to 2 panels in bonded-DSI mode Jun Nie 2026-05-21 14:46 ` [PATCH v4 1/5] drm/msm/dsi: support DSC configurations with slice_per_pkt > 1 Jun Nie 2026-05-21 15:08 ` sashiko-bot 2026-05-21 14:46 ` [PATCH v4 2/5] drm/mipi-dsi: Add flag to support dual-panel configurations Jun Nie 2026-05-21 15:20 ` sashiko-bot 2026-05-21 14:46 ` [PATCH v4 3/5] drm/msm/dsi: Support dual panel use case with single CRTC Jun Nie 2026-05-21 15:50 ` sashiko-bot 2026-05-21 14:46 ` [PATCH v4 4/5] dt-bindings: display: Add Synaptics R63455 panel support Jun Nie 2026-05-21 16:07 ` sashiko-bot 2026-05-21 19:45 ` Conor Dooley 2026-05-21 20:24 ` Dmitry Baryshkov 2026-05-22 6:32 ` Neil Armstrong 2026-05-21 20:46 ` Rob Herring (Arm) 2026-05-21 14:46 ` [PATCH v4 5/5] drm/panel: Add driver for Synaptics R63455 DSI panel Jun Nie 2026-05-21 16:30 ` sashiko-bot
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox