why:
HDMI 2.1 sinks advertise their VRR range in the HDMI Forum VSDB
(HF-VSDB), but amdgpu derived FreeSync capability only from the AMD
VSDB. Sinks that expose just the HDMI Forum VRR capability (e.g. HDMI
compliance EDIDs) were therefore reported as not VRR capable.

how:
- In amdgpu_dm_update_freesync_caps(), when the AMD VSDB does not
  provide a valid FreeSync range, fall back to the HDMI 2.1 VRR range
  parsed by DRM core from the HF-VSDB
  (connector->display_info.hdmi.vrr_cap). VRRMAX = 0 means "up to the
  Base Refresh Rate"; when the EDID provides no monitor range maximum
  either, fall back to the Base Refresh Rate (the highest refresh-rate
  mode of the preferred timing) so a valid VRR range is still reported
  to userspace.
- Add VRR debug logging along the FreeSync capability and config paths.

Signed-off-by: Fangzhi Zuo <[email protected]>
---
 .../display/amdgpu_dm/amdgpu_dm_connector.c   | 67 +++++++++++++++++++
 .../display/amdgpu_dm/amdgpu_dm_freesync.c    |  8 +++
 2 files changed, 75 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c
index 5e7ab9158995..df39bc70ec6c 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c
@@ -3812,6 +3812,15 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector 
*connector,
        if (!adev->dm.freesync_module || 
!dc_supports_vrr(sink->ctx->dce_version))
                goto update;
 
+       drm_dbg_driver(adev_to_drm(adev),
+                      "VRR: enter signal=%d hdmi_vrr=%d mrange[%d-%d] 
hdmi.vrr_cap[sup=%d min=%d max=%d]\n",
+                      sink->sink_signal, 
connector->display_info.hdmi.vrr_cap.supported,
+                      connector->display_info.monitor_range.min_vfreq,
+                      connector->display_info.monitor_range.max_vfreq,
+                      connector->display_info.hdmi.vrr_cap.supported,
+                      connector->display_info.hdmi.vrr_cap.vrr_min,
+                      connector->display_info.hdmi.vrr_cap.vrr_max);
+
        /* FIXME: Get rid of drm_edid_raw() */
        edid = drm_edid_raw(drm_edid);
 
@@ -3856,6 +3865,59 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector 
*connector,
                                connector->display_info.monitor_range.max_vfreq 
= vsdb_info.max_refresh_rate_hz;
                        }
                }
+
+               drm_dbg_driver(adev_to_drm(adev),
+                              "VRR: amd_vsdb i=%d fs_sup=%d min=%d max=%d 
fs_capable=%d\n",
+                              i, vsdb_info.freesync_supported,
+                              vsdb_info.min_refresh_rate_hz,
+                              vsdb_info.max_refresh_rate_hz, freesync_capable);
+
+               /*
+                * If AMD VSDB didn't provide a valid FreeSync range, fall back 
to
+                * the HDMI 2.1 VRR capability parsed from the HF-VSDB.
+                */
+               if (!freesync_capable && 
connector->display_info.hdmi.vrr_cap.supported) {
+                       struct drm_hdmi_vrr_cap *vrr_cap =
+                               &connector->display_info.hdmi.vrr_cap;
+
+                       drm_dbg_driver(adev_to_drm(adev),
+                                      "VRR: HF-VSDB fallback: hdmi_vrr=1 
vrr_cap[sup=%d min=%d max=%d] mrange_max=%d\n",
+                                      vrr_cap->supported, vrr_cap->vrr_min, 
vrr_cap->vrr_max,
+                                      
connector->display_info.monitor_range.max_vfreq);
+
+                       if (vrr_cap->supported && vrr_cap->vrr_min > 0) {
+                               amdgpu_dm_connector->min_vfreq = 
vrr_cap->vrr_min;
+                               amdgpu_dm_connector->max_vfreq = 
vrr_cap->vrr_max ?
+                                       vrr_cap->vrr_max :
+                                       
connector->display_info.monitor_range.max_vfreq;
+
+                               /*
+                                * VRRMAX = 0 in the HF-VSDB means "up to the 
Base
+                                * Refresh Rate". If the EDID also did not 
provide a
+                                * monitor range max, fall back to the Base 
Refresh
+                                * Rate (the highest refresh rate of the 
preferred
+                                * timing) so a valid VRR range is still 
reported to
+                                * userspace.
+                                */
+                               if (!amdgpu_dm_connector->max_vfreq) {
+                                       struct drm_display_mode *brr_mode =
+                                               
amdgpu_dm_get_highest_refresh_rate_mode(amdgpu_dm_connector, true);
+
+                                       if (brr_mode)
+                                               amdgpu_dm_connector->max_vfreq =
+                                                       
drm_mode_vrefresh(brr_mode);
+                               }
+
+                               if (amdgpu_dm_connector->max_vfreq -
+                                   amdgpu_dm_connector->min_vfreq > 10)
+                                       freesync_capable = true;
+
+                               connector->display_info.monitor_range.min_vfreq 
=
+                                       amdgpu_dm_connector->min_vfreq;
+                               connector->display_info.monitor_range.max_vfreq 
=
+                                       amdgpu_dm_connector->max_vfreq;
+                       }
+               }
        }
 
        if (amdgpu_dm_connector->dc_link)
@@ -3899,6 +3961,11 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector 
*connector,
        if (dm_con_state)
                dm_con_state->freesync_capable = freesync_capable;
 
+       drm_dbg_driver(adev_to_drm(adev),
+                      "VRR: caps result: freesync_capable=%d min_vfreq=%d 
max_vfreq=%d\n",
+                      freesync_capable, amdgpu_dm_connector->min_vfreq,
+                      amdgpu_dm_connector->max_vfreq);
+
        if (connector->state && amdgpu_dm_connector->dc_link && 
!freesync_capable &&
            
amdgpu_dm_connector->dc_link->replay_settings.config.replay_supported) {
                
amdgpu_dm_connector->dc_link->replay_settings.config.replay_supported = false;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_freesync.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_freesync.c
index 1fa078cdba52..cb49184813de 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_freesync.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_freesync.c
@@ -152,6 +152,14 @@ void amdgpu_dm_get_freesync_config_for_crtc(
        }
 out:
        new_crtc_state->freesync_config = config;
+
+       drm_dbg_driver(new_con_state->base.connector->dev,
+                      "VRR: cfg vrr_enabled=%d vrr_supported=%d fs_capable=%d 
vrefresh=%d min=%d max=%d state=%d\n",
+                      new_crtc_state->base.vrr_enabled,
+                      new_crtc_state->vrr_supported,
+                      new_con_state->freesync_capable, vrefresh,
+                      aconnector->min_vfreq, aconnector->max_vfreq,
+                      config.state);
 }
 EXPORT_IF_KUNIT(amdgpu_dm_get_freesync_config_for_crtc);
 
-- 
2.53.0

Reply via email to