YUV420 uses colorimetry VSC packets, which cannot share the automatic
PSR packet generator. Do not advertise self-refresh eligibility for
these streams while disabling PSR in the controller and sink.

Compute eligibility after the common atomic check and reject an
incompatible self-refresh entry. Clear the automatic VSC generation bit
for YUV420 and restore PSR configuration when returning to RGB.

Assisted-by: LLM
Signed-off-by: Xilin Wu <[email protected]>
---
 drivers/gpu/drm/msm/dp/dp_ctrl.c    | 19 ++++++++++++-------
 drivers/gpu/drm/msm/dp/dp_ctrl.h    |  2 +-
 drivers/gpu/drm/msm/dp/dp_display.c |  3 ++-
 drivers/gpu/drm/msm/dp/dp_drm.c     | 16 ++++++++++++----
 4 files changed, 27 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c
index 783cafb22374..82ef8e405543 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
@@ -411,7 +411,7 @@ static void msm_dp_ctrl_config_ctrl_streams(struct 
msm_dp_ctrl_private *ctrl,
 
        config |= tbd << DP_CONFIGURATION_CTRL_BPC_SHIFT;
 
-       if (msm_dp_panel->psr_cap.version)
+       if (msm_dp_panel->psr_cap.version && 
!msm_dp_panel->msm_dp_mode.out_fmt_is_yuv_420)
                config |= DP_CONFIGURATION_CTRL_SEND_VSC;
 
        drm_dbg_dp(ctrl->drm_dev, "stream DP_CONFIGURATION_CTRL=0x%x\n", 
config);
@@ -1914,7 +1914,7 @@ static void msm_dp_ctrl_psr_exit(struct 
msm_dp_ctrl_private *ctrl)
 }
 
 void msm_dp_ctrl_config_psr(struct msm_dp_ctrl *msm_dp_ctrl,
-                           struct msm_dp_panel *panel)
+                           struct msm_dp_panel *panel, bool enable)
 {
        struct msm_dp_ctrl_private *ctrl = container_of(msm_dp_ctrl,
                        struct msm_dp_ctrl_private, msm_dp_ctrl);
@@ -1923,15 +1923,20 @@ void msm_dp_ctrl_config_psr(struct msm_dp_ctrl 
*msm_dp_ctrl,
        if (!panel->psr_cap.version)
                return;
 
-       /* enable PSR1 function */
+       /* Colorimetry VSC packets cannot share the PSR packet generator. */
        cfg = msm_dp_read_link(ctrl, REG_PSR_CONFIG);
-       cfg |= PSR1_SUPPORTED;
+       if (enable)
+               cfg |= PSR1_SUPPORTED;
+       else
+               cfg &= ~PSR1_SUPPORTED;
        msm_dp_write_link(ctrl, REG_PSR_CONFIG, cfg);
 
-       msm_dp_ctrl_config_psr_interrupt(ctrl);
-       msm_dp_ctrl_enable_sdp(ctrl);
+       if (enable) {
+               msm_dp_ctrl_config_psr_interrupt(ctrl);
+               msm_dp_ctrl_enable_sdp(ctrl);
+       }
 
-       cfg = DP_PSR_ENABLE;
+       cfg = enable ? DP_PSR_ENABLE : 0;
        drm_dp_dpcd_write(ctrl->aux, DP_PSR_EN_CFG, &cfg, 1);
 }
 
diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h b/drivers/gpu/drm/msm/dp/dp_ctrl.h
index 42c5f847cb02..4dd604ef9f1b 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.h
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.h
@@ -46,7 +46,7 @@ void msm_dp_ctrl_irq_phy_exit(struct msm_dp_ctrl 
*msm_dp_ctrl);
 void msm_dp_ctrl_set_psr(struct msm_dp_ctrl *msm_dp_ctrl,
                         struct msm_dp_panel *panel, bool enable);
 void msm_dp_ctrl_config_psr(struct msm_dp_ctrl *msm_dp_ctrl,
-                           struct msm_dp_panel *panel);
+                           struct msm_dp_panel *panel, bool enable);
 
 int msm_dp_ctrl_core_clk_enable(struct msm_dp_ctrl *msm_dp_ctrl);
 void msm_dp_ctrl_core_clk_disable(struct msm_dp_ctrl *msm_dp_ctrl);
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index 486348113b8a..234cb2373451 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -822,7 +822,8 @@ static int msm_dp_display_post_enable(struct msm_dp 
*msm_dp_display)
        msm_dp_display_handle_plugged_change(msm_dp_display, true);
 
        if (msm_dp_display->psr_supported)
-               msm_dp_ctrl_config_psr(dp->ctrl, dp->panel);
+               msm_dp_ctrl_config_psr(dp->ctrl, dp->panel,
+                                      
!dp->panel->msm_dp_mode.out_fmt_is_yuv_420);
 
        return 0;
 }
diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c
index 9f1aa87a3687..6b01eeeb1aef 100644
--- a/drivers/gpu/drm/msm/dp/dp_drm.c
+++ b/drivers/gpu/drm/msm/dp/dp_drm.c
@@ -204,19 +204,27 @@ static int msm_edp_bridge_atomic_check(struct drm_bridge 
*drm_bridge,
                                   struct drm_connector_state *conn_state)
 {
        struct msm_dp *dp = to_dp_bridge(drm_bridge)->msm_dp_display;
+       int ret;
 
        if (WARN_ON(!conn_state))
                return -ENODEV;
 
-       conn_state->self_refresh_aware = dp->psr_supported;
-
+       conn_state->self_refresh_aware = false;
        if (!conn_state->crtc || !crtc_state)
                return 0;
 
-       if (crtc_state->self_refresh_active && !dp->psr_supported)
+       ret = msm_dp_bridge_atomic_check(drm_bridge, bridge_state, crtc_state, 
conn_state);
+       if (ret)
+               return ret;
+
+       /* Match the PSR configuration applied when enabling this stream. */
+       conn_state->self_refresh_aware = dp->psr_supported &&
+               !drm_mode_is_420_only(&conn_state->connector->display_info,
+                                   &crtc_state->adjusted_mode);
+       if (crtc_state->self_refresh_active && !conn_state->self_refresh_aware)
                return -EINVAL;
 
-       return msm_dp_bridge_atomic_check(drm_bridge, bridge_state, crtc_state, 
conn_state);
+       return 0;
 }
 
 static void msm_edp_bridge_atomic_enable(struct drm_bridge *drm_bridge,

-- 
2.56.0

Reply via email to