Commit 585b2f68 authored by Timur Kristóf's avatar Timur Kristóf Committed by Alex Deucher
Browse files

drm/amdgpu: Respect max pixel clock for HDMI and DVI-D (v2)



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: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarTimur Kristóf <timur.kristof@gmail.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 220b2bd5
Loading
Loading
Loading
Loading
+44 −13
Original line number Diff line number Diff line
@@ -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 */