aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJerome Glisse <jglisse@redhat.com>2011-07-25 11:57:43 -0400
committerDave Airlie <airlied@redhat.com>2011-07-26 07:30:55 -0400
commit5a96a899bbdee86024ab9ea6d02b9e242faacbed (patch)
treeaf48e2ad77177f56d5448c89eaec95d5ccb5aff7
parent4639dd21e759e32125adc7171abf6cb8140d54cf (diff)
drm/radeon/kms: fix DP training for DPEncoderService revision bigger than 1.1
DPEncoderService newer than 1.1 can't properly program the DP (display port) link training. When facing such version use the DIGxEncoderControl method instead. Fix DP link training on some R7XX. Signed-off-by: Jerome Glisse <jglisse@redhat.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Cc: stable@kernel.org Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--drivers/gpu/drm/radeon/atombios_dp.c22
1 files changed, 18 insertions, 4 deletions
diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c
index 8c0f9e36ff8e..645b84b3d203 100644
--- a/drivers/gpu/drm/radeon/atombios_dp.c
+++ b/drivers/gpu/drm/radeon/atombios_dp.c
@@ -627,6 +627,7 @@ struct radeon_dp_link_train_info {
627 u8 train_set[4]; 627 u8 train_set[4];
628 u8 link_status[DP_LINK_STATUS_SIZE]; 628 u8 link_status[DP_LINK_STATUS_SIZE];
629 u8 tries; 629 u8 tries;
630 bool use_dpencoder;
630}; 631};
631 632
632static void radeon_dp_update_vs_emph(struct radeon_dp_link_train_info *dp_info) 633static void radeon_dp_update_vs_emph(struct radeon_dp_link_train_info *dp_info)
@@ -646,7 +647,7 @@ static void radeon_dp_set_tp(struct radeon_dp_link_train_info *dp_info, int tp)
646 int rtp = 0; 647 int rtp = 0;
647 648
648 /* set training pattern on the source */ 649 /* set training pattern on the source */
649 if (ASIC_IS_DCE4(dp_info->rdev)) { 650 if (ASIC_IS_DCE4(dp_info->rdev) || !dp_info->use_dpencoder) {
650 switch (tp) { 651 switch (tp) {
651 case DP_TRAINING_PATTERN_1: 652 case DP_TRAINING_PATTERN_1:
652 rtp = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN1; 653 rtp = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN1;
@@ -706,7 +707,7 @@ static int radeon_dp_link_train_init(struct radeon_dp_link_train_info *dp_info)
706 radeon_write_dpcd_reg(dp_info->radeon_connector, DP_LINK_BW_SET, tmp); 707 radeon_write_dpcd_reg(dp_info->radeon_connector, DP_LINK_BW_SET, tmp);
707 708
708 /* start training on the source */ 709 /* start training on the source */
709 if (ASIC_IS_DCE4(dp_info->rdev)) 710 if (ASIC_IS_DCE4(dp_info->rdev) || !dp_info->use_dpencoder)
710 atombios_dig_encoder_setup(dp_info->encoder, 711 atombios_dig_encoder_setup(dp_info->encoder,
711 ATOM_ENCODER_CMD_DP_LINK_TRAINING_START, 0); 712 ATOM_ENCODER_CMD_DP_LINK_TRAINING_START, 0);
712 else 713 else
@@ -731,7 +732,7 @@ static int radeon_dp_link_train_finish(struct radeon_dp_link_train_info *dp_info
731 DP_TRAINING_PATTERN_DISABLE); 732 DP_TRAINING_PATTERN_DISABLE);
732 733
733 /* disable the training pattern on the source */ 734 /* disable the training pattern on the source */
734 if (ASIC_IS_DCE4(dp_info->rdev)) 735 if (ASIC_IS_DCE4(dp_info->rdev) || !dp_info->use_dpencoder)
735 atombios_dig_encoder_setup(dp_info->encoder, 736 atombios_dig_encoder_setup(dp_info->encoder,
736 ATOM_ENCODER_CMD_DP_LINK_TRAINING_COMPLETE, 0); 737 ATOM_ENCODER_CMD_DP_LINK_TRAINING_COMPLETE, 0);
737 else 738 else
@@ -869,7 +870,8 @@ void radeon_dp_link_train(struct drm_encoder *encoder,
869 struct radeon_connector *radeon_connector; 870 struct radeon_connector *radeon_connector;
870 struct radeon_connector_atom_dig *dig_connector; 871 struct radeon_connector_atom_dig *dig_connector;
871 struct radeon_dp_link_train_info dp_info; 872 struct radeon_dp_link_train_info dp_info;
872 u8 tmp; 873 int index;
874 u8 tmp, frev, crev;
873 875
874 if (!radeon_encoder->enc_priv) 876 if (!radeon_encoder->enc_priv)
875 return; 877 return;
@@ -884,6 +886,18 @@ void radeon_dp_link_train(struct drm_encoder *encoder,
884 (dig_connector->dp_sink_type != CONNECTOR_OBJECT_ID_eDP)) 886 (dig_connector->dp_sink_type != CONNECTOR_OBJECT_ID_eDP))
885 return; 887 return;
886 888
889 /* DPEncoderService newer than 1.1 can't program properly the
890 * training pattern. When facing such version use the
891 * DIGXEncoderControl (X== 1 | 2)
892 */
893 dp_info.use_dpencoder = true;
894 index = GetIndexIntoMasterTable(COMMAND, DPEncoderService);
895 if (atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) {
896 if (crev > 1) {
897 dp_info.use_dpencoder = false;
898 }
899 }
900
887 dp_info.enc_id = 0; 901 dp_info.enc_id = 0;
888 if (dig->dig_encoder) 902 if (dig->dig_encoder)
889 dp_info.enc_id |= ATOM_DP_CONFIG_DIG2_ENCODER; 903 dp_info.enc_id |= ATOM_DP_CONFIG_DIG2_ENCODER;