From: Michal Bielaga <[email protected]>

Variable Refresh Rate (VRR/FreeSync) currently only works with
Single-Stream Transport (SST) DisplayPort connections. Monitors
connected via MST hubs cannot utilize VRR even when they support it,
because the driver only enables VRR for SST connections.

This patch enables VRR for DisplayPort MST by:
- Including SIGNAL_TYPE_DISPLAY_PORT_MST in VRR capability detection
- Reading VRR range from display EDID instead of MST hub DPCD, since
  dc_link points to the hub rather than the actual display
- Fixing call order to parse EDID before checking VRR capabilities,
  ensuring display_info.monitor_range is populated
- Properly attaching VRR property to MST connectors by reusing the
  master connector's property

Without this patch, MST displays cannot use VRR even if they support
it, limiting the user experience for multi-monitor DisplayPort MST
setups.

Signed-off-by: Michal Bielaga <[email protected]>
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c     | 11 +++++++++--
 .../drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c   |  9 ++++++---
 2 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index ef026143dc1c..ac5b6c22361f 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -12644,9 +12644,16 @@ void amdgpu_dm_update_freesync_caps(struct 
drm_connector *connector,
                parse_edid_displayid_vrr(connector, edid);
 
        if (edid && (sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT ||
+                    sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT_MST ||
                     sink->sink_signal == SIGNAL_TYPE_EDP)) {
-               if (amdgpu_dm_connector->dc_link &&
-                   
amdgpu_dm_connector->dc_link->dpcd_caps.allow_invalid_MSA_timing_param) {
+               /* For MST, check monitor range from EDID directly since the 
dc_link
+                * points to the MST hub, not the actual display
+                */
+               if ((sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT_MST ||
+                    (amdgpu_dm_connector->dc_link &&
+                     
amdgpu_dm_connector->dc_link->dpcd_caps.allow_invalid_MSA_timing_param)) &&
+                   connector->display_info.monitor_range.min_vfreq &&
+                   connector->display_info.monitor_range.max_vfreq) {
                        amdgpu_dm_connector->min_vfreq = 
connector->display_info.monitor_range.min_vfreq;
                        amdgpu_dm_connector->max_vfreq = 
connector->display_info.monitor_range.max_vfreq;
                        if (amdgpu_dm_connector->max_vfreq - 
amdgpu_dm_connector->min_vfreq > 10)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index 77a9d2c7d318..062259514b3c 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -443,6 +443,9 @@ static int dm_dp_mst_get_modes(struct drm_connector 
*connector)
                        }
                }
 
+               /* Update connector with EDID first so 
display_info.monitor_range is populated */
+               drm_edid_connector_update(&aconnector->base, 
aconnector->drm_edid);
+
                if (aconnector->dc_sink) {
                        amdgpu_dm_update_freesync_caps(
                                        connector, aconnector->drm_edid);
@@ -459,8 +462,6 @@ static int dm_dp_mst_get_modes(struct drm_connector 
*connector)
                }
        }
 
-       drm_edid_connector_update(&aconnector->base, aconnector->drm_edid);
-
        ret = drm_edid_connector_add_modes(connector);
 
        return ret;
@@ -650,9 +651,11 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr 
*mgr,
        if (connector->max_bpc_property)
                drm_connector_attach_max_bpc_property(connector, 8, 16);
 
+       /* Reuse VRR property from master connector for MST connectors */
        connector->vrr_capable_property = master->base.vrr_capable_property;
        if (connector->vrr_capable_property)
-               drm_connector_attach_vrr_capable_property(connector);
+               drm_object_attach_property(&connector->base,
+                                          connector->vrr_capable_property, 0);
 
        drm_object_attach_property(
                &connector->base,
-- 
2.51.1


Reply via email to