diff options
| -rw-r--r-- | drivers/gpu/drm/radeon/atombios_dp.c | 23 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_encoders.c | 163 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_mode.h | 2 |
3 files changed, 99 insertions, 89 deletions
diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c index 9c023d25aad0..71060114d5de 100644 --- a/drivers/gpu/drm/radeon/atombios_dp.c +++ b/drivers/gpu/drm/radeon/atombios_dp.c | |||
| @@ -596,21 +596,14 @@ void dp_link_train(struct drm_encoder *encoder, | |||
| 596 | return; | 596 | return; |
| 597 | dig_connector = radeon_connector->con_priv; | 597 | dig_connector = radeon_connector->con_priv; |
| 598 | 598 | ||
| 599 | if (ASIC_IS_DCE32(rdev)) { | 599 | if (dig->dig_encoder) |
| 600 | if (dig->dig_block) | 600 | enc_id |= ATOM_DP_CONFIG_DIG2_ENCODER; |
| 601 | enc_id |= ATOM_DP_CONFIG_DIG2_ENCODER; | 601 | else |
| 602 | else | 602 | enc_id |= ATOM_DP_CONFIG_DIG1_ENCODER; |
| 603 | enc_id |= ATOM_DP_CONFIG_DIG1_ENCODER; | 603 | if (dig_connector->linkb) |
| 604 | if (dig_connector->linkb) | 604 | enc_id |= ATOM_DP_CONFIG_LINK_B; |
| 605 | enc_id |= ATOM_DP_CONFIG_LINK_B; | 605 | else |
| 606 | else | 606 | enc_id |= ATOM_DP_CONFIG_LINK_A; |
| 607 | enc_id |= ATOM_DP_CONFIG_LINK_A; | ||
| 608 | } else { | ||
| 609 | if (dig_connector->linkb) | ||
| 610 | enc_id |= ATOM_DP_CONFIG_DIG2_ENCODER | ATOM_DP_CONFIG_LINK_B; | ||
| 611 | else | ||
| 612 | enc_id |= ATOM_DP_CONFIG_DIG1_ENCODER | ATOM_DP_CONFIG_LINK_A; | ||
| 613 | } | ||
| 614 | 607 | ||
| 615 | memset(link_configuration, 0, DP_LINK_CONFIGURATION_SIZE); | 608 | memset(link_configuration, 0, DP_LINK_CONFIGURATION_SIZE); |
| 616 | if (dig_connector->dp_clock == 270000) | 609 | if (dig_connector->dp_clock == 270000) |
diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index 10746c9c8051..3c91724457ca 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c | |||
| @@ -156,6 +156,26 @@ radeon_get_encoder_id(struct drm_device *dev, uint32_t supported_device, uint8_t | |||
| 156 | return ret; | 156 | return ret; |
| 157 | } | 157 | } |
| 158 | 158 | ||
| 159 | static inline bool radeon_encoder_is_digital(struct drm_encoder *encoder) | ||
| 160 | { | ||
| 161 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 162 | switch (radeon_encoder->encoder_id) { | ||
| 163 | case ENCODER_OBJECT_ID_INTERNAL_LVDS: | ||
| 164 | case ENCODER_OBJECT_ID_INTERNAL_TMDS1: | ||
| 165 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: | ||
| 166 | case ENCODER_OBJECT_ID_INTERNAL_LVTM1: | ||
| 167 | case ENCODER_OBJECT_ID_INTERNAL_DVO1: | ||
| 168 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: | ||
| 169 | case ENCODER_OBJECT_ID_INTERNAL_DDI: | ||
| 170 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: | ||
| 171 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: | ||
| 172 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: | ||
| 173 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: | ||
| 174 | return true; | ||
| 175 | default: | ||
| 176 | return false; | ||
| 177 | } | ||
| 178 | } | ||
| 159 | void | 179 | void |
| 160 | radeon_link_encoder_connector(struct drm_device *dev) | 180 | radeon_link_encoder_connector(struct drm_device *dev) |
| 161 | { | 181 | { |
| @@ -676,31 +696,11 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action) | |||
| 676 | 696 | ||
| 677 | memset(&args, 0, sizeof(args)); | 697 | memset(&args, 0, sizeof(args)); |
| 678 | 698 | ||
| 679 | if (ASIC_IS_DCE32(rdev)) { | 699 | if (dig->dig_encoder) |
| 680 | if (dig->dig_block) | 700 | index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl); |
| 681 | index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl); | 701 | else |
| 682 | else | 702 | index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl); |
| 683 | index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl); | 703 | num = dig->dig_encoder + 1; |
| 684 | num = dig->dig_block + 1; | ||
| 685 | } else { | ||
| 686 | switch (radeon_encoder->encoder_id) { | ||
| 687 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: | ||
| 688 | /* XXX doesn't really matter which dig encoder we pick as long as it's | ||
| 689 | * not already in use | ||
| 690 | */ | ||
| 691 | if (dig_connector->linkb) | ||
| 692 | index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl); | ||
| 693 | else | ||
| 694 | index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl); | ||
| 695 | num = 1; | ||
| 696 | break; | ||
| 697 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: | ||
| 698 | /* Only dig2 encoder can drive LVTMA */ | ||
| 699 | index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl); | ||
| 700 | num = 2; | ||
| 701 | break; | ||
| 702 | } | ||
| 703 | } | ||
| 704 | 704 | ||
| 705 | atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev); | 705 | atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev); |
| 706 | 706 | ||
| @@ -822,7 +822,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t | |||
| 822 | args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); | 822 | args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); |
| 823 | } | 823 | } |
| 824 | if (ASIC_IS_DCE32(rdev)) { | 824 | if (ASIC_IS_DCE32(rdev)) { |
| 825 | if (dig->dig_block) | 825 | if (dig->dig_encoder == 1) |
| 826 | args.v2.acConfig.ucEncoderSel = 1; | 826 | args.v2.acConfig.ucEncoderSel = 1; |
| 827 | if (dig_connector->linkb) | 827 | if (dig_connector->linkb) |
| 828 | args.v2.acConfig.ucLinkSel = 1; | 828 | args.v2.acConfig.ucLinkSel = 1; |
| @@ -849,17 +849,16 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t | |||
| 849 | args.v2.acConfig.fCoherentMode = 1; | 849 | args.v2.acConfig.fCoherentMode = 1; |
| 850 | } | 850 | } |
| 851 | } else { | 851 | } else { |
| 852 | |||
| 852 | args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL; | 853 | args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL; |
| 853 | 854 | ||
| 855 | if (dig->dig_encoder) | ||
| 856 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER; | ||
| 857 | else | ||
| 858 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER; | ||
| 859 | |||
| 854 | switch (radeon_encoder->encoder_id) { | 860 | switch (radeon_encoder->encoder_id) { |
| 855 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: | 861 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: |
| 856 | /* XXX doesn't really matter which dig encoder we pick as long as it's | ||
| 857 | * not already in use | ||
| 858 | */ | ||
| 859 | if (dig_connector->linkb) | ||
| 860 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER; | ||
| 861 | else | ||
| 862 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER; | ||
| 863 | if (rdev->flags & RADEON_IS_IGP) { | 862 | if (rdev->flags & RADEON_IS_IGP) { |
| 864 | if (radeon_encoder->pixel_clock > 165000) { | 863 | if (radeon_encoder->pixel_clock > 165000) { |
| 865 | if (dig_connector->igp_lane_info & 0x3) | 864 | if (dig_connector->igp_lane_info & 0x3) |
| @@ -878,10 +877,6 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t | |||
| 878 | } | 877 | } |
| 879 | } | 878 | } |
| 880 | break; | 879 | break; |
| 881 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: | ||
| 882 | /* Only dig2 encoder can drive LVTMA */ | ||
| 883 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER; | ||
| 884 | break; | ||
| 885 | } | 880 | } |
| 886 | 881 | ||
| 887 | if (radeon_encoder->pixel_clock > 165000) | 882 | if (radeon_encoder->pixel_clock > 165000) |
| @@ -1046,6 +1041,7 @@ atombios_set_encoder_crtc_source(struct drm_encoder *encoder) | |||
| 1046 | union crtc_sourc_param args; | 1041 | union crtc_sourc_param args; |
| 1047 | int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source); | 1042 | int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source); |
| 1048 | uint8_t frev, crev; | 1043 | uint8_t frev, crev; |
| 1044 | struct radeon_encoder_atom_dig *dig; | ||
| 1049 | 1045 | ||
| 1050 | memset(&args, 0, sizeof(args)); | 1046 | memset(&args, 0, sizeof(args)); |
| 1051 | 1047 | ||
| @@ -1109,40 +1105,16 @@ atombios_set_encoder_crtc_source(struct drm_encoder *encoder) | |||
| 1109 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: | 1105 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: |
| 1110 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: | 1106 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: |
| 1111 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: | 1107 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: |
| 1112 | if (ASIC_IS_DCE32(rdev)) { | 1108 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: |
| 1113 | if (radeon_crtc->crtc_id) | 1109 | dig = radeon_encoder->enc_priv; |
| 1114 | args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID; | 1110 | if (dig->dig_encoder) |
| 1115 | else | 1111 | args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID; |
| 1116 | args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID; | 1112 | else |
| 1117 | } else { | 1113 | args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID; |
| 1118 | struct drm_connector *connector; | ||
| 1119 | struct radeon_connector *radeon_connector; | ||
| 1120 | struct radeon_connector_atom_dig *dig_connector; | ||
| 1121 | |||
| 1122 | connector = radeon_get_connector_for_encoder(encoder); | ||
| 1123 | if (!connector) | ||
| 1124 | return; | ||
| 1125 | radeon_connector = to_radeon_connector(connector); | ||
| 1126 | if (!radeon_connector->con_priv) | ||
| 1127 | return; | ||
| 1128 | dig_connector = radeon_connector->con_priv; | ||
| 1129 | |||
| 1130 | /* XXX doesn't really matter which dig encoder we pick as long as it's | ||
| 1131 | * not already in use | ||
| 1132 | */ | ||
| 1133 | if (dig_connector->linkb) | ||
| 1134 | args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID; | ||
| 1135 | else | ||
| 1136 | args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID; | ||
| 1137 | } | ||
| 1138 | break; | 1114 | break; |
| 1139 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: | 1115 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: |
| 1140 | args.v2.ucEncoderID = ASIC_INT_DVO_ENCODER_ID; | 1116 | args.v2.ucEncoderID = ASIC_INT_DVO_ENCODER_ID; |
| 1141 | break; | 1117 | break; |
| 1142 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: | ||
| 1143 | /* Only dig2 encoder can drive LVTMA */ | ||
| 1144 | args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID; | ||
| 1145 | break; | ||
| 1146 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: | 1118 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: |
| 1147 | if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) | 1119 | if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) |
| 1148 | args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; | 1120 | args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; |
| @@ -1202,6 +1174,47 @@ atombios_apply_encoder_quirks(struct drm_encoder *encoder, | |||
| 1202 | } | 1174 | } |
| 1203 | } | 1175 | } |
| 1204 | 1176 | ||
| 1177 | static int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder) | ||
| 1178 | { | ||
| 1179 | struct drm_device *dev = encoder->dev; | ||
| 1180 | struct radeon_device *rdev = dev->dev_private; | ||
| 1181 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); | ||
| 1182 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 1183 | struct drm_encoder *test_encoder; | ||
| 1184 | struct radeon_encoder_atom_dig *dig; | ||
| 1185 | uint32_t dig_enc_in_use = 0; | ||
| 1186 | /* on DCE32 and encoder can driver any block so just crtc id */ | ||
| 1187 | if (ASIC_IS_DCE32(rdev)) { | ||
| 1188 | return radeon_crtc->crtc_id; | ||
| 1189 | } | ||
| 1190 | |||
| 1191 | /* on DCE3 - LVTMA can only be driven by DIGB */ | ||
| 1192 | list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) { | ||
| 1193 | struct radeon_encoder *radeon_test_encoder; | ||
| 1194 | |||
| 1195 | if (encoder == test_encoder) | ||
| 1196 | continue; | ||
| 1197 | |||
| 1198 | if (!radeon_encoder_is_digital(test_encoder)) | ||
| 1199 | continue; | ||
| 1200 | |||
| 1201 | radeon_test_encoder = to_radeon_encoder(test_encoder); | ||
| 1202 | dig = radeon_test_encoder->enc_priv; | ||
| 1203 | |||
| 1204 | if (dig->dig_encoder >= 0) | ||
| 1205 | dig_enc_in_use |= (1 << dig->dig_encoder); | ||
| 1206 | } | ||
| 1207 | |||
| 1208 | if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA) { | ||
| 1209 | if (dig_enc_in_use & 0x2) | ||
| 1210 | DRM_ERROR("LVDS required digital encoder 2 but it was in use - stealing\n"); | ||
| 1211 | return 1; | ||
| 1212 | } | ||
| 1213 | if (!(dig_enc_in_use & 1)) | ||
| 1214 | return 0; | ||
| 1215 | return 1; | ||
| 1216 | } | ||
| 1217 | |||
| 1205 | static void | 1218 | static void |
| 1206 | radeon_atom_encoder_mode_set(struct drm_encoder *encoder, | 1219 | radeon_atom_encoder_mode_set(struct drm_encoder *encoder, |
| 1207 | struct drm_display_mode *mode, | 1220 | struct drm_display_mode *mode, |
| @@ -1214,12 +1227,9 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder, | |||
| 1214 | 1227 | ||
| 1215 | if (radeon_encoder->active_device & | 1228 | if (radeon_encoder->active_device & |
| 1216 | (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) { | 1229 | (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) { |
| 1217 | if (radeon_encoder->enc_priv) { | 1230 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
| 1218 | struct radeon_encoder_atom_dig *dig; | 1231 | if (dig) |
| 1219 | 1232 | dig->dig_encoder = radeon_atom_pick_dig_encoder(encoder); | |
| 1220 | dig = radeon_encoder->enc_priv; | ||
| 1221 | dig->dig_block = radeon_crtc->crtc_id; | ||
| 1222 | } | ||
| 1223 | } | 1233 | } |
| 1224 | radeon_encoder->pixel_clock = adjusted_mode->clock; | 1234 | radeon_encoder->pixel_clock = adjusted_mode->clock; |
| 1225 | 1235 | ||
| @@ -1379,7 +1389,13 @@ static void radeon_atom_encoder_commit(struct drm_encoder *encoder) | |||
| 1379 | static void radeon_atom_encoder_disable(struct drm_encoder *encoder) | 1389 | static void radeon_atom_encoder_disable(struct drm_encoder *encoder) |
| 1380 | { | 1390 | { |
| 1381 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 1391 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
| 1392 | struct radeon_encoder_atom_dig *dig; | ||
| 1382 | radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); | 1393 | radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); |
| 1394 | |||
| 1395 | if (radeon_encoder_is_digital(encoder)) { | ||
| 1396 | dig = radeon_encoder->enc_priv; | ||
| 1397 | dig->dig_encoder = -1; | ||
| 1398 | } | ||
| 1383 | radeon_encoder->active_device = 0; | 1399 | radeon_encoder->active_device = 0; |
| 1384 | } | 1400 | } |
| 1385 | 1401 | ||
| @@ -1436,6 +1452,7 @@ radeon_atombios_set_dig_info(struct radeon_encoder *radeon_encoder) | |||
| 1436 | 1452 | ||
| 1437 | /* coherent mode by default */ | 1453 | /* coherent mode by default */ |
| 1438 | dig->coherent_mode = true; | 1454 | dig->coherent_mode = true; |
| 1455 | dig->dig_encoder = -1; | ||
| 1439 | 1456 | ||
| 1440 | return dig; | 1457 | return dig; |
| 1441 | } | 1458 | } |
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 96b851f92f4c..e81b2aeb6a8f 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h | |||
| @@ -299,7 +299,7 @@ struct radeon_atom_ss { | |||
| 299 | struct radeon_encoder_atom_dig { | 299 | struct radeon_encoder_atom_dig { |
| 300 | /* atom dig */ | 300 | /* atom dig */ |
| 301 | bool coherent_mode; | 301 | bool coherent_mode; |
| 302 | int dig_block; | 302 | int dig_encoder; /* -1 disabled, 0 DIGA, 1 DIGB */ |
| 303 | /* atom lvds */ | 303 | /* atom lvds */ |
| 304 | uint32_t lvds_misc; | 304 | uint32_t lvds_misc; |
| 305 | uint16_t panel_pwr_delay; | 305 | uint16_t panel_pwr_delay; |
