Re: [PATCH v4 15/39] drm/msm/dp: Add support for programming p1/p2/p3 register blocks

Dmitry Baryshkov
2026-04-11T18:07:59Z

On Fri, Apr 10, 2026 at 05:33:50PM +0800, Yongxing Mou wrote:
> From: Abhinav Kumar <quic_abhinavk@quicinc.com>
>
> Add support for additional pixel register blocks (p1, p2, p3) to enable
> 4‑stream MST pixel clocks. Introduce the helper functions msm_dp_read_pn
> and msm_dp_write_pn for pixel register programming. All pixel clocks
> share the same register layout but use different base addresses.
>
> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> Signed-off-by: Yongxing Mou <yongxing.mou@oss.qualcomm.com>
> ---
> drivers/gpu/drm/msm/dp/dp_display.c | 40 ++++++++++++-----
> drivers/gpu/drm/msm/dp/dp_panel.c | 89 ++++++++++++++++++++-----------------
> drivers/gpu/drm/msm/dp/dp_panel.h | 3 +-
> 3 files changed, 79 insertions(+), 53 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
> index 7984a0f9e938..ff506064a3fa 100644
> --- a/drivers/gpu/drm/msm/dp/dp_display.c
> +++ b/drivers/gpu/drm/msm/dp/dp_display.c
> @@ -85,8 +85,8 @@ struct msm_dp_display_private {
> void __iomem *link_base;
> size_t link_len;
>
> - void __iomem *p0_base;
> - size_t p0_len;
> + void __iomem *pixel_base[DP_STREAM_MAX];
> + size_t pixel_len;
>
> int max_stream;
> };
> @@ -561,7 +561,7 @@ static int msm_dp_init_sub_modules(struct msm_dp_display_private *dp)
> goto error_link;
> }
>
> - dp->panel = msm_dp_panel_get(dev, dp->aux, dp->link, dp->link_base, dp->p0_base);
> + dp->panel = msm_dp_panel_get(dev, dp->aux, dp->link, dp->link_base, dp->pixel_base[0]);
> if (IS_ERR(dp->panel)) {
> rc = PTR_ERR(dp->panel);
> DRM_ERROR("failed to initialize panel, rc = %d\n", rc);
> @@ -769,6 +769,7 @@ int msm_dp_display_set_stream_info(struct msm_dp *msm_dp_display,
> }
>
> panel->stream_id = stream_id;
> + msm_dp_panel_set_pixel_base(panel, dp->pixel_base[stream_id]);

Hmmm.... Would it be better to set it up differently? Allocate one panel
per the stream from the beginning and then simply get the first
available panel when required? This would require some minimal resource
manager, but then we won't have to pass dummy register base to the panel
code. Or actually allocate a panel when it is required? Do we need a
panel before atomic_enable()?

>
> return rc;
> }
> @@ -882,8 +883,14 @@ void msm_dp_snapshot(struct msm_disp_state *disp_state, struct msm_dp *dp)
> msm_dp_display->aux_base, "dp_aux");
> msm_disp_snapshot_add_block(disp_state, msm_dp_display->link_len,
> msm_dp_display->link_base, "dp_link");
> - msm_disp_snapshot_add_block(disp_state, msm_dp_display->p0_len,
> - msm_dp_display->p0_base, "dp_p0");
> + msm_disp_snapshot_add_block(disp_state, msm_dp_display->pixel_len,
> + msm_dp_display->pixel_base[0], "dp_p0");
> + msm_disp_snapshot_add_block(disp_state, msm_dp_display->pixel_len,
> + msm_dp_display->pixel_base[1], "dp_p1");
> + msm_disp_snapshot_add_block(disp_state, msm_dp_display->pixel_len,
> + msm_dp_display->pixel_base[2], "dp_p2");
> + msm_disp_snapshot_add_block(disp_state, msm_dp_display->pixel_len,
> + msm_dp_display->pixel_base[3], "dp_p3");
> }
>
> void msm_dp_display_set_psr(struct msm_dp *msm_dp_display, bool enter)
> @@ -1163,6 +1170,7 @@ static void __iomem *msm_dp_ioremap(struct platform_device *pdev, int idx, size_
> static int msm_dp_display_get_io(struct msm_dp_display_private *display)
> {
> struct platform_device *pdev = display->msm_dp_display.pdev;
> + int i;
>
> display->ahb_base = msm_dp_ioremap(pdev, 0, &display->ahb_len);
> if (IS_ERR(display->ahb_base))
> @@ -1192,8 +1200,8 @@ static int msm_dp_display_get_io(struct msm_dp_display_private *display)
> display->aux_len = DP_DEFAULT_AUX_SIZE;
> display->link_base = display->ahb_base + DP_DEFAULT_LINK_OFFSET;
> display->link_len = DP_DEFAULT_LINK_SIZE;
> - display->p0_base = display->ahb_base + DP_DEFAULT_P0_OFFSET;
> - display->p0_len = DP_DEFAULT_P0_SIZE;
> + display->pixel_base[0] = display->ahb_base + DP_DEFAULT_P0_OFFSET;
> + display->pixel_len = DP_DEFAULT_P0_SIZE;
>
> return 0;
> }
> @@ -1204,10 +1212,20 @@ static int msm_dp_display_get_io(struct msm_dp_display_private *display)
> return PTR_ERR(display->link_base);
> }
>
> - display->p0_base = msm_dp_ioremap(pdev, 3, &display->p0_len);
> - if (IS_ERR(display->p0_base)) {
> - DRM_ERROR("unable to remap p0 region: %pe\n", display->p0_base);
> - return PTR_ERR(display->p0_base);
> + display->pixel_base[0] = msm_dp_ioremap(pdev, 3, &display->pixel_len);
> + if (IS_ERR(display->pixel_base[0])) {
> + DRM_ERROR("unable to remap p0 region: %pe\n", display->pixel_base[0]);
> + return PTR_ERR(display->pixel_base[0]);
> + }
> +
> + for (i = DP_STREAM_1; i < display->max_stream; i++) {
> + /* pixels clk reg index start from 3*/
> + display->pixel_base[i] = msm_dp_ioremap(pdev, i + 3, &display->pixel_len);
> + if (IS_ERR(display->pixel_base[i])) {
> + DRM_DEBUG_DP("unable to remap p%d region: %pe\n", i,
> + display->pixel_base[i]);
> + break;

No, return an error.

> + }
> }
>
> return 0;

--
With best wishes
Dmitry