From: Abhinav Kumar <[email protected]>

Each MST stream uses its own pixel register block. Extend pixel
register access beyond p0 to support up to four streams.

Not all controllers provide all four blocks. Check for optional
resources before mapping them to avoid misleading probe errors when
they are absent, while propagating mapping failures for resources
that are present.

Track each block's size separately so register snapshots use the
size of the corresponding resource.

Signed-off-by: Abhinav Kumar <[email protected]>
Signed-off-by: Yongxing Mou <[email protected]>
---
 drivers/gpu/drm/msm/dp/dp_ctrl.c    | 10 +++++
 drivers/gpu/drm/msm/dp/dp_ctrl.h    |  2 +
 drivers/gpu/drm/msm/dp/dp_display.c | 56 ++++++++++++++++++-----
 drivers/gpu/drm/msm/dp/dp_panel.c   | 90 ++++++++++++++++++-------------------
 drivers/gpu/drm/msm/dp/dp_panel.h   |  2 +-
 5 files changed, 103 insertions(+), 57 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c
index 67f1da46b973..c0f5226dc383 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
@@ -2770,6 +2770,16 @@ static int msm_dp_ctrl_clk_init(struct msm_dp_ctrl 
*msm_dp_ctrl)
        return 0;
 }
 
+bool msm_dp_ctrl_stream_clks_on(struct msm_dp_ctrl *msm_dp_ctrl,
+                               enum msm_dp_stream_id stream_id)
+{
+       struct msm_dp_ctrl_private *ctrl;
+
+       ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, 
msm_dp_ctrl);
+
+       return ctrl->stream_clks_on[stream_id];
+}
+
 struct msm_dp_ctrl *msm_dp_ctrl_get(struct device *dev, struct msm_dp_link 
*link,
                        struct drm_dp_aux *aux,
                        struct phy *phy,
diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h b/drivers/gpu/drm/msm/dp/dp_ctrl.h
index be0d89d60914..bf593f4a4480 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.h
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.h
@@ -55,4 +55,6 @@ void msm_dp_ctrl_enable_irq(struct msm_dp_ctrl *msm_dp_ctrl);
 void msm_dp_ctrl_disable_irq(struct msm_dp_ctrl *msm_dp_ctrl);
 
 void msm_dp_ctrl_reinit_phy(struct msm_dp_ctrl *msm_dp_ctrl);
+bool msm_dp_ctrl_stream_clks_on(struct msm_dp_ctrl *dp_ctrl,
+                               enum msm_dp_stream_id stream_id);
 #endif /* _DP_CTRL_H_ */
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index 01a60b4f83e9..d8b28a562653 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[DP_STREAM_MAX];
 };
 
 struct msm_dp_desc {
@@ -562,7 +562,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);
@@ -846,8 +846,13 @@ 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");
+
+       for (int i = 0; i < DP_STREAM_MAX; i++) {
+               if (!msm_dp_ctrl_stream_clks_on(msm_dp_display->ctrl, i))
+                       continue;
+               msm_disp_snapshot_add_block(disp_state, 
msm_dp_display->pixel_len[i],
+                                           msm_dp_display->pixel_base[i], 
"dp_p%d", i);
+       }
 }
 
 void msm_dp_display_set_psr(struct msm_dp *msm_dp_display, bool enter)
@@ -1115,6 +1120,26 @@ static void __iomem *msm_dp_ioremap(struct 
platform_device *pdev, int idx, size_
        return base;
 }
 
+static void __iomem *msm_dp_ioremap_optional(struct platform_device *pdev,
+                                            int idx, size_t *len)
+{
+       struct resource *res;
+       void __iomem *base;
+
+       if (len)
+               *len = 0;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, idx);
+       if (!res)
+               return NULL;
+
+       base = devm_ioremap_resource(&pdev->dev, res);
+       if (!IS_ERR(base))
+               *len = resource_size(res);
+
+       return base;
+}
+
 #define DP_DEFAULT_AHB_OFFSET  0x0000
 #define DP_DEFAULT_AHB_SIZE    0x0200
 #define DP_DEFAULT_AUX_OFFSET  0x0200
@@ -1127,6 +1152,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))
@@ -1156,8 +1182,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_STREAM_0] = DP_DEFAULT_P0_SIZE;
 
                return 0;
        }
@@ -1168,10 +1194,18 @@ 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[DP_STREAM_0]);
+       if (IS_ERR(display->pixel_base[0]))
+               return PTR_ERR(display->pixel_base[0]);
+
+       for (i = DP_STREAM_1; i < DP_STREAM_MAX; i++) {
+               display->pixel_base[i] = msm_dp_ioremap_optional(pdev, i + 3,
+                                                          
&display->pixel_len[i]);
+               if (IS_ERR(display->pixel_base[i]))
+                       return PTR_ERR(display->pixel_base[i]);
+               if (!display->pixel_base[i])
+                       break;
        }
 
        return 0;
diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c 
b/drivers/gpu/drm/msm/dp/dp_panel.c
index 745ee6976897..7b5fc5bb16de 100644
--- a/drivers/gpu/drm/msm/dp/dp_panel.c
+++ b/drivers/gpu/drm/msm/dp/dp_panel.c
@@ -25,7 +25,7 @@ struct msm_dp_panel_private {
        struct drm_dp_aux *aux;
        struct msm_dp_link *link;
        void __iomem *link_base;
-       void __iomem *p0_base;
+       void __iomem *pixel_base;
        bool panel_on;
 };
 
@@ -44,24 +44,24 @@ static inline void msm_dp_write_link(struct 
msm_dp_panel_private *panel,
        writel(data, panel->link_base + offset);
 }
 
-static inline void msm_dp_write_p0(struct msm_dp_panel_private *panel,
-                              u32 offset, u32 data)
+static inline void msm_dp_write_pn(struct msm_dp_panel_private *panel,
+                                  u32 offset, u32 data)
 {
        /*
-        * To make sure interface reg writes happens before any other operation,
-        * this function uses writel() instread of writel_relaxed()
+        * Use writel() instead of writel_relaxed() to ensure the interface
+        * register write reaches the hardware before subsequent operations.
         */
-       writel(data, panel->p0_base + offset);
+       writel(data, panel->pixel_base + offset);
 }
 
-static inline u32 msm_dp_read_p0(struct msm_dp_panel_private *panel,
-                              u32 offset)
+static inline u32 msm_dp_read_pn(struct msm_dp_panel_private *panel,
+                                u32 offset)
 {
        /*
-        * To make sure interface reg writes happens before any other operation,
-        * this function uses writel() instread of writel_relaxed()
+        * Only reads a configuration register: no DMA or memory ordering is
+        * required, so readl_relaxed() is sufficient.
         */
-       return readl_relaxed(panel->p0_base + offset);
+       return readl_relaxed(panel->pixel_base + offset);
 }
 
 static void msm_dp_panel_read_psr_cap(struct msm_dp_panel_private *panel)
@@ -367,34 +367,34 @@ static void msm_dp_panel_tpg_enable(struct msm_dp_panel 
*msm_dp_panel,
        display_hctl = (hsync_end_x << 16) | hsync_start_x;
 
 
-       msm_dp_write_p0(panel, MMSS_DP_INTF_HSYNC_CTL, hsync_ctl);
-       msm_dp_write_p0(panel, MMSS_DP_INTF_VSYNC_PERIOD_F0, vsync_period *
+       msm_dp_write_pn(panel, MMSS_DP_INTF_HSYNC_CTL, hsync_ctl);
+       msm_dp_write_pn(panel, MMSS_DP_INTF_VSYNC_PERIOD_F0, vsync_period *
                        hsync_period);
-       msm_dp_write_p0(panel, MMSS_DP_INTF_VSYNC_PULSE_WIDTH_F0, v_sync_width *
+       msm_dp_write_pn(panel, MMSS_DP_INTF_VSYNC_PULSE_WIDTH_F0, v_sync_width *
                        hsync_period);
-       msm_dp_write_p0(panel, MMSS_DP_INTF_VSYNC_PERIOD_F1, 0);
-       msm_dp_write_p0(panel, MMSS_DP_INTF_VSYNC_PULSE_WIDTH_F1, 0);
-       msm_dp_write_p0(panel, MMSS_DP_INTF_DISPLAY_HCTL, display_hctl);
-       msm_dp_write_p0(panel, MMSS_DP_INTF_ACTIVE_HCTL, 0);
-       msm_dp_write_p0(panel, MMSS_INTF_DISPLAY_V_START_F0, display_v_start);
-       msm_dp_write_p0(panel, MMSS_DP_INTF_DISPLAY_V_END_F0, display_v_end);
-       msm_dp_write_p0(panel, MMSS_INTF_DISPLAY_V_START_F1, 0);
-       msm_dp_write_p0(panel, MMSS_DP_INTF_DISPLAY_V_END_F1, 0);
-       msm_dp_write_p0(panel, MMSS_DP_INTF_ACTIVE_V_START_F0, 0);
-       msm_dp_write_p0(panel, MMSS_DP_INTF_ACTIVE_V_END_F0, 0);
-       msm_dp_write_p0(panel, MMSS_DP_INTF_ACTIVE_V_START_F1, 0);
-       msm_dp_write_p0(panel, MMSS_DP_INTF_ACTIVE_V_END_F1, 0);
-       msm_dp_write_p0(panel, MMSS_DP_INTF_POLARITY_CTL, 0);
-
-       msm_dp_write_p0(panel, MMSS_DP_TPG_MAIN_CONTROL,
-                               DP_TPG_CHECKERED_RECT_PATTERN);
-       msm_dp_write_p0(panel, MMSS_DP_TPG_VIDEO_CONFIG,
-                               DP_TPG_VIDEO_CONFIG_BPP_8BIT |
-                               DP_TPG_VIDEO_CONFIG_RGB);
-       msm_dp_write_p0(panel, MMSS_DP_BIST_ENABLE,
-                               DP_BIST_ENABLE_DPBIST_EN);
-       msm_dp_write_p0(panel, MMSS_DP_TIMING_ENGINE_EN,
-                               DP_TIMING_ENGINE_EN_EN);
+       msm_dp_write_pn(panel, MMSS_DP_INTF_VSYNC_PERIOD_F1, 0);
+       msm_dp_write_pn(panel, MMSS_DP_INTF_VSYNC_PULSE_WIDTH_F1, 0);
+       msm_dp_write_pn(panel, MMSS_DP_INTF_DISPLAY_HCTL, display_hctl);
+       msm_dp_write_pn(panel, MMSS_DP_INTF_ACTIVE_HCTL, 0);
+       msm_dp_write_pn(panel, MMSS_INTF_DISPLAY_V_START_F0, display_v_start);
+       msm_dp_write_pn(panel, MMSS_DP_INTF_DISPLAY_V_END_F0, display_v_end);
+       msm_dp_write_pn(panel, MMSS_INTF_DISPLAY_V_START_F1, 0);
+       msm_dp_write_pn(panel, MMSS_DP_INTF_DISPLAY_V_END_F1, 0);
+       msm_dp_write_pn(panel, MMSS_DP_INTF_ACTIVE_V_START_F0, 0);
+       msm_dp_write_pn(panel, MMSS_DP_INTF_ACTIVE_V_END_F0, 0);
+       msm_dp_write_pn(panel, MMSS_DP_INTF_ACTIVE_V_START_F1, 0);
+       msm_dp_write_pn(panel, MMSS_DP_INTF_ACTIVE_V_END_F1, 0);
+       msm_dp_write_pn(panel, MMSS_DP_INTF_POLARITY_CTL, 0);
+
+       msm_dp_write_pn(panel, MMSS_DP_TPG_MAIN_CONTROL,
+                       DP_TPG_CHECKERED_RECT_PATTERN);
+       msm_dp_write_pn(panel, MMSS_DP_TPG_VIDEO_CONFIG,
+                       DP_TPG_VIDEO_CONFIG_BPP_8BIT |
+                       DP_TPG_VIDEO_CONFIG_RGB);
+       msm_dp_write_pn(panel, MMSS_DP_BIST_ENABLE,
+                       DP_BIST_ENABLE_DPBIST_EN);
+       msm_dp_write_pn(panel, MMSS_DP_TIMING_ENGINE_EN,
+                       DP_TIMING_ENGINE_EN_EN);
        drm_dbg_dp(panel->drm_dev, "%s: enabled tpg\n", __func__);
 }
 
@@ -403,9 +403,9 @@ static void msm_dp_panel_tpg_disable(struct msm_dp_panel 
*msm_dp_panel)
        struct msm_dp_panel_private *panel =
                container_of(msm_dp_panel, struct msm_dp_panel_private, 
msm_dp_panel);
 
-       msm_dp_write_p0(panel, MMSS_DP_TPG_MAIN_CONTROL, 0x0);
-       msm_dp_write_p0(panel, MMSS_DP_BIST_ENABLE, 0x0);
-       msm_dp_write_p0(panel, MMSS_DP_TIMING_ENGINE_EN, 0x0);
+       msm_dp_write_pn(panel, MMSS_DP_TPG_MAIN_CONTROL, 0x0);
+       msm_dp_write_pn(panel, MMSS_DP_BIST_ENABLE, 0x0);
+       msm_dp_write_pn(panel, MMSS_DP_TIMING_ENGINE_EN, 0x0);
 }
 
 void msm_dp_panel_tpg_config(struct msm_dp_panel *msm_dp_panel, bool enable)
@@ -439,7 +439,7 @@ void msm_dp_panel_clear_dsc_dto(struct msm_dp_panel 
*msm_dp_panel)
        struct msm_dp_panel_private *panel =
                container_of(msm_dp_panel, struct msm_dp_panel_private, 
msm_dp_panel);
 
-       msm_dp_write_p0(panel, MMSS_DP_DSC_DTO, 0x0);
+       msm_dp_write_pn(panel, MMSS_DP_DSC_DTO, 0x0);
 }
 
 static void msm_dp_panel_send_vsc_sdp(struct msm_dp_panel_private *panel, 
struct dp_sdp *vsc_sdp)
@@ -629,7 +629,7 @@ int msm_dp_panel_timing_cfg(struct msm_dp_panel 
*msm_dp_panel, bool wide_bus_en)
        msm_dp_write_link(panel, REG_DP_HSYNC_VSYNC_WIDTH_POLARITY, 
width_blanking);
        msm_dp_write_link(panel, REG_DP_ACTIVE_HOR_VER, msm_dp_active);
 
-       reg = msm_dp_read_p0(panel, MMSS_DP_INTF_CONFIG);
+       reg = msm_dp_read_pn(panel, MMSS_DP_INTF_CONFIG);
        if (wide_bus_en)
                reg |= DP_INTF_CONFIG_DATABUS_WIDEN;
        else
@@ -637,7 +637,7 @@ int msm_dp_panel_timing_cfg(struct msm_dp_panel 
*msm_dp_panel, bool wide_bus_en)
 
        drm_dbg_dp(panel->drm_dev, "wide_bus_en=%d reg=%#x\n", wide_bus_en, 
reg);
 
-       msm_dp_write_p0(panel, MMSS_DP_INTF_CONFIG, reg);
+       msm_dp_write_pn(panel, MMSS_DP_INTF_CONFIG, reg);
 
        if (msm_dp_panel->msm_dp_mode.out_fmt_is_yuv_420)
                msm_dp_panel_setup_vsc_sdp_yuv_420(msm_dp_panel);
@@ -701,7 +701,7 @@ int msm_dp_panel_init_panel_info(struct msm_dp_panel 
*msm_dp_panel,
 struct msm_dp_panel *msm_dp_panel_get(struct device *dev, struct drm_dp_aux 
*aux,
                              struct msm_dp_link *link,
                              void __iomem *link_base,
-                             void __iomem *p0_base)
+                             void __iomem *pixel_base)
 {
        struct msm_dp_panel_private *panel;
        struct msm_dp_panel *msm_dp_panel;
@@ -719,7 +719,7 @@ struct msm_dp_panel *msm_dp_panel_get(struct device *dev, 
struct drm_dp_aux *aux
        panel->aux = aux;
        panel->link = link;
        panel->link_base = link_base;
-       panel->p0_base = p0_base;
+       panel->pixel_base = pixel_base;
 
        msm_dp_panel = &panel->msm_dp_panel;
        msm_dp_panel->max_bw_code = DP_LINK_BW_8_1;
diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h 
b/drivers/gpu/drm/msm/dp/dp_panel.h
index 50a721401751..218a09a2fa65 100644
--- a/drivers/gpu/drm/msm/dp/dp_panel.h
+++ b/drivers/gpu/drm/msm/dp/dp_panel.h
@@ -102,5 +102,5 @@ static inline bool is_lane_count_valid(u32 lane_count)
 struct msm_dp_panel *msm_dp_panel_get(struct device *dev, struct drm_dp_aux 
*aux,
                              struct msm_dp_link *link,
                              void __iomem *link_base,
-                             void __iomem *p0_base);
+                             void __iomem *pixel_base);
 #endif /* _DP_PANEL_H_ */

-- 
2.43.0

Reply via email to