]> www.infradead.org Git - users/hch/misc.git/commitdiff
drm/amd/display: Skip Check Runtime Link Setting for Specific Branch Device
authorFangzhi Zuo <Jerry.Zuo@amd.com>
Thu, 14 Aug 2025 18:41:44 +0000 (14:41 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Fri, 29 Aug 2025 14:23:09 +0000 (10:23 -0400)
[why]
Read link setting inside mode validation is not always the final downlink setting.
It is found true in Synaptics branch device.

At bootup, the preferred mode being set right after 1080p is set. It occurred
before graphic load. That modeset switch in a short period of time makes
the branch device switch back and forth from lower and higher link rate,
observed at Synaptics branch device.
DP2 RTK hub on the other hand, sticks to highest available downlink rate after bootup.

Existing check of runtime downlink setting in mode validation shows asynchronous at
branch device link switch, i.e., downlink switch to higher link rate not yet complete
when the mode validation tries to probe the downlink setting. That makes mode validation
checking downlink setting making wrong decision by pruning modes that should pass the
validation after the downlink setting switch is complete.

[how]
If Synaptics is found at the last branch, skip checking downlink setting
at mode validation.

Reviewed-by: Wayne Lin <wayne.lin@amd.com>
Signed-off-by: Fangzhi Zuo <Jerry.Zuo@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
Tested-by: Dan Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c

index cbd107493f8ac913e614f34deed3536921e90be6..ce74125c713e9a8223b6032dc9735c3fbbe58a11 100644 (file)
@@ -768,6 +768,9 @@ struct amdgpu_dm_connector {
        uint16_t vc_full_pbn;
        struct mutex handle_mst_msg_ready;
 
+       /* branch device specific data */
+       uint32_t branch_ieee_oui;
+
        /* TODO see if we can merge with ddc_bus or make a dm_connector */
        struct amdgpu_i2c_adapter *i2c;
 
index 32281bf62f706ce8b4db7b7203bf819de703e297..6a817508c826574bde9b011b01eb4f84c45ae267 100644 (file)
@@ -330,6 +330,34 @@ static bool retrieve_downstream_port_device(struct amdgpu_dm_connector *aconnect
        return true;
 }
 
+static bool retrieve_branch_specific_data(struct amdgpu_dm_connector *aconnector)
+{
+       struct drm_connector *connector = &aconnector->base;
+       struct drm_dp_mst_port *port = aconnector->mst_output_port;
+       struct drm_dp_mst_port *port_parent;
+       struct drm_dp_aux *immediate_upstream_aux;
+       struct drm_dp_desc branch_desc;
+
+       if (!port->parent)
+               return false;
+
+       port_parent = port->parent->port_parent;
+
+       immediate_upstream_aux = port_parent ? &port_parent->aux : port->mgr->aux;
+
+       if (drm_dp_read_desc(immediate_upstream_aux, &branch_desc, true))
+               return false;
+
+       aconnector->branch_ieee_oui = (branch_desc.ident.oui[0] << 16) +
+                                     (branch_desc.ident.oui[1] << 8) +
+                                     (branch_desc.ident.oui[2]);
+
+       drm_dbg_dp(port->aux.drm_dev, "MST branch oui 0x%x detected at %s\n",
+                  aconnector->branch_ieee_oui, connector->name);
+
+       return true;
+}
+
 static int dm_dp_mst_get_modes(struct drm_connector *connector)
 {
        struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
@@ -669,6 +697,9 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
 
        drm_connector_set_path_property(connector, pathprop);
 
+       if (!retrieve_branch_specific_data(aconnector))
+               aconnector->branch_ieee_oui = 0;
+
        /*
         * Initialize connector state before adding the connectror to drm and
         * framebuffer lists
@@ -1774,6 +1805,9 @@ static bool dp_get_link_current_set_bw(struct drm_dp_aux *aux, uint32_t *cur_lin
        link_bw_set = data[DP_LINK_BW_SET - DP_LINK_BW_SET];
        lane_count.raw = data[DP_LANE_COUNT_SET - DP_LINK_BW_SET];
 
+       drm_dbg_dp(aux->drm_dev, "MST_DSC downlink setting: %d, 0x%x x %d\n",
+                  dp_link_encoding, link_bw_set, lane_count.bits.LANE_COUNT_SET);
+
        switch (dp_link_encoding) {
        case DP_8b_10b_ENCODING:
                link_rate = link_bw_set;
@@ -1870,8 +1904,10 @@ enum dc_status dm_dp_mst_is_port_support_mode(
                                        end_link_bw = aconnector->mst_local_bw;
                                }
 
-                               if (end_link_bw > 0 && stream_kbps > end_link_bw) {
-                                       DRM_DEBUG_DRIVER("MST_DSC dsc decode at last link."
+                               if (end_link_bw > 0 &&
+                                   stream_kbps > end_link_bw &&
+                                   aconnector->branch_ieee_oui != DP_BRANCH_DEVICE_ID_90CC24) {
+                                       DRM_DEBUG_DRIVER("MST_DSC dsc decode at last link. "
                                                         "Mode required bw can't fit into last link\n");
                                        return DC_FAIL_BANDWIDTH_VALIDATE;
                                }