From bf227d40e47cd92733681090f99dba9f18493cba Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 11 May 2015 10:29:29 -0400 Subject: [PATCH] drm/radeon: grab dpcd info from vbios for eDP The DPCD for some eDP panels may not be reliable. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/atombios_dp.c | 22 +++++++++++++++++++--- drivers/gpu/drm/radeon/atombios_encoders.c | 2 +- drivers/gpu/drm/radeon/radeon_atombios.c | 9 +++++++++ drivers/gpu/drm/radeon/radeon_mode.h | 9 ++++++++- 4 files changed, 37 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c index 3e3290c..be08e2a 100644 --- a/drivers/gpu/drm/radeon/atombios_dp.c +++ b/drivers/gpu/drm/radeon/atombios_dp.c @@ -471,9 +471,14 @@ int radeon_dp_get_panel_mode(struct drm_encoder *encoder, panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; } } else if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; /* eDP */ - if (drm_dp_dpcd_readb(&radeon_connector->ddc_bus->aux, - DP_EDP_CONFIGURATION_CAP, &tmp) == 1) { + if (dig->atom_dpcd_valid) { + if (dig->dpcd_edp_conf_cap & 1) + panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; + } else if (drm_dp_dpcd_readb(&radeon_connector->ddc_bus->aux, + DP_EDP_CONFIGURATION_CAP, &tmp) == 1) { if (tmp & 1) panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; } @@ -482,9 +487,11 @@ int radeon_dp_get_panel_mode(struct drm_encoder *encoder, return panel_mode; } -void radeon_dp_set_link_config(struct drm_connector *connector, +void radeon_dp_set_link_config(struct drm_encoder *encoder, + struct drm_connector *connector, const struct drm_display_mode *mode) { + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct radeon_connector *radeon_connector = to_radeon_connector(connector); struct radeon_connector_atom_dig *dig_connector; @@ -494,6 +501,15 @@ void radeon_dp_set_link_config(struct drm_connector *connector, if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) { + if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { + struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; + + if (dig->atom_dpcd_valid) { + dig_connector->dpcd[DP_MAX_LINK_RATE] = dig->dpcd_max_link_rate; + dig_connector->dpcd[DP_MAX_LANE_COUNT] = dig->dpcd_max_lane_count; + dig_connector->dpcd[DP_MAX_DOWNSPREAD] = dig->dpcd_max_downspread; + } + } dig_connector->dp_clock = radeon_dp_get_dp_link_clock(connector, dig_connector->dpcd, mode->clock); dig_connector->dp_lane_count = diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index dd39f43..5d94f27 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c @@ -330,7 +330,7 @@ static bool radeon_atom_mode_fixup(struct drm_encoder *encoder, ((radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) || (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE))) { struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); - radeon_dp_set_link_config(connector, adjusted_mode); + radeon_dp_set_link_config(encoder, connector, adjusted_mode); } return true; diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 8f28524..25056a6 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -1596,6 +1596,7 @@ bool radeon_atombios_get_asic_ss_info(struct radeon_device *rdev, union lvds_info { struct _ATOM_LVDS_INFO info; struct _ATOM_LVDS_INFO_V12 info_12; + struct _ATOM_LCD_INFO_V13 info_13; }; struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct @@ -1671,6 +1672,14 @@ struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct else lvds->linkb = false; + if ((frev == 1) && (crev >= 3)) { + lvds->dpcd_edp_conf_cap = lvds_info->info_13.ucDPCD_eDP_CONFIGURATION_CAP; + lvds->dpcd_max_link_rate = lvds_info->info_13.ucDPCD_MAX_LINK_RATE; + lvds->dpcd_max_lane_count = lvds_info->info_13.ucDPCD_MAX_LANE_COUNT; + lvds->dpcd_max_downspread = lvds_info->info_13.ucDPCD_MAX_DOWNSPREAD; + lvds->atom_dpcd_valid = true; + } + /* parse the lcd record table */ if (le16_to_cpu(lvds_info->info.usModePatchTableOffset)) { ATOM_FAKE_EDID_PATCH_RECORD *fake_edid_record; diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index fa91a17..305aafa 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -441,6 +441,12 @@ struct radeon_encoder_atom_dig { int panel_mode; struct radeon_afmt *afmt; int active_mst_links; + /* atom eDP conf overrides */ + bool atom_dpcd_valid; + u8 dpcd_edp_conf_cap; + u8 dpcd_max_link_rate; + u8 dpcd_max_lane_count; + u8 dpcd_max_downspread; }; struct radeon_encoder_atom_dac { @@ -744,7 +750,8 @@ extern struct edid *radeon_connector_edid(struct drm_connector *connector); extern void radeon_connector_hotplug(struct drm_connector *connector); extern int radeon_dp_mode_valid_helper(struct drm_connector *connector, struct drm_display_mode *mode); -extern void radeon_dp_set_link_config(struct drm_connector *connector, +extern void radeon_dp_set_link_config(struct drm_encoder *encoder, + struct drm_connector *connector, const struct drm_display_mode *mode); extern void radeon_dp_link_train(struct drm_encoder *encoder, struct drm_connector *connector); -- 1.8.3.1