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
