On Mon, Jul 27, 2026 at 04:08:43PM +0800, Jun Nie wrote:
> 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.

I guess, the flag from the previous patch should be coming from the DT
node of the DSI host. The DSI should then get the mode from a single
panel and then set the adjusted_mode for the CRTC (note sure how this
will work for the compositors though).


Also please note that the are other possible configurations. For
example, for some time I've had a setup using two Raspberry panels
attached to two DSI hosts for exactly the same purpose (please check, I
think Neil might still have it, or maybe somebody else from the team).
Each channel is an I2C-controlled DSI-to-DPI bridge + a DPI panel. I
understand that it's not your target, but it's something to keep in
mind. I'd say, the bare minimum would be to resolve a second bridge (be
it a full bridge or a panel bridge), possibly create a second bridge
chain (remember, bridges don't support branching, so you are a bit on
your own here) and at least manually call the callbacks. This would
ensure that the second panel (or a second bridge) is properly controlled
(and thus would get rid of the second reset GPIO from your patches).

> The pic_width is used to calculated DSC parameter for DPU DSC controller
>  together with panel's parameter. While panel driver that support dual
> panel shall provide slice_width parameter of single panel. This patch
> only impact DSC configuration, so crtc is not aware of it and not impacted
> by it.
> 
> 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.

broadcasting of DSI commands is controlled by the DT flag.

> 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 <[email protected]>
> ---
>  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 e39938fb0f502..a3c56c3dc7904 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;
> @@ -2600,6 +2605,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
> 

-- 
With best wishes
Dmitry

Reply via email to