]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
drm/amdgpu: Respect max pixel clock for HDMI and DVI-D (v2)
authorTimur Kristóf <timur.kristof@gmail.com>
Thu, 28 Aug 2025 14:50:36 +0000 (16:50 +0200)
committerAlex Deucher <alexander.deucher@amd.com>
Fri, 29 Aug 2025 14:23:09 +0000 (10:23 -0400)
Update the legacy (non-DC) display code to respect the maximum
pixel clock for HDMI and DVI-D. Reject modes that would require
a higher pixel clock than can be supported.

Also update the maximum supported HDMI clock value depending on
the ASIC type.

For reference, see the DC code:
check max_hdmi_pixel_clock in dce*_resource.c

v2:
Fix maximum clocks for DVI-D and DVI/HDMI adapters.

Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c

index 5e375e9c4f5de3883797f06a0c4bea26bf3d1795..a381de8648e54b2602835da7b4c6e75d839a4d99 100644 (file)
@@ -1195,29 +1195,60 @@ static void amdgpu_connector_dvi_force(struct drm_connector *connector)
                amdgpu_connector->use_digital = true;
 }
 
+/**
+ * Returns the maximum supported HDMI (TMDS) pixel clock in KHz.
+ */
+static int amdgpu_max_hdmi_pixel_clock(const struct amdgpu_device *adev)
+{
+       if (adev->asic_type >= CHIP_POLARIS10)
+               return 600000;
+       else if (adev->asic_type >= CHIP_TONGA)
+               return 300000;
+       else
+               return 297000;
+}
+
+/**
+ * Validates the given display mode on DVI and HDMI connectors,
+ * including analog signals on DVI-I.
+ */
 static enum drm_mode_status amdgpu_connector_dvi_mode_valid(struct drm_connector *connector,
                                            const struct drm_display_mode *mode)
 {
        struct drm_device *dev = connector->dev;
        struct amdgpu_device *adev = drm_to_adev(dev);
        struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
+       const int max_hdmi_pixel_clock = amdgpu_max_hdmi_pixel_clock(adev);
+       const int max_dvi_single_link_pixel_clock = 165000;
+       int max_digital_pixel_clock_khz;
 
        /* XXX check mode bandwidth */
 
-       if (amdgpu_connector->use_digital && (mode->clock > 165000)) {
-               if ((amdgpu_connector->connector_object_id == CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I) ||
-                   (amdgpu_connector->connector_object_id == CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D) ||
-                   (amdgpu_connector->connector_object_id == CONNECTOR_OBJECT_ID_HDMI_TYPE_B)) {
-                       return MODE_OK;
-               } else if (connector->display_info.is_hdmi) {
-                       /* HDMI 1.3+ supports max clock of 340 Mhz */
-                       if (mode->clock > 340000)
-                               return MODE_CLOCK_HIGH;
-                       else
-                               return MODE_OK;
-               } else {
-                       return MODE_CLOCK_HIGH;
+       if (amdgpu_connector->use_digital) {
+               switch (amdgpu_connector->connector_object_id) {
+               case CONNECTOR_OBJECT_ID_HDMI_TYPE_A:
+                       max_digital_pixel_clock_khz = max_hdmi_pixel_clock;
+                       break;
+               case CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I:
+               case CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D:
+                       max_digital_pixel_clock_khz = max_dvi_single_link_pixel_clock;
+                       break;
+               case CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I:
+               case CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D:
+               case CONNECTOR_OBJECT_ID_HDMI_TYPE_B:
+                       max_digital_pixel_clock_khz = max_dvi_single_link_pixel_clock * 2;
+                       break;
                }
+
+               /* When the display EDID claims that it's an HDMI display,
+                * we use the HDMI encoder mode of the display HW,
+                * so we should verify against the max HDMI clock here.
+                */
+               if (connector->display_info.is_hdmi)
+                       max_digital_pixel_clock_khz = max_hdmi_pixel_clock;
+
+               if (mode->clock > max_digital_pixel_clock_khz)
+                       return MODE_CLOCK_HIGH;
        }
 
        /* check against the max pixel clock */