diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c | 57 | 
1 files changed, 44 insertions, 13 deletions
| diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c index 5e375e9c4f5d..a381de8648e5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c @@ -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 */ | 
