diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_encoders.c')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_encoders.c | 179 |
1 files changed, 99 insertions, 80 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index ccba95f83d11..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 | { |
@@ -202,7 +222,7 @@ radeon_get_connector_for_encoder(struct drm_encoder *encoder) | |||
202 | 222 | ||
203 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 223 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
204 | radeon_connector = to_radeon_connector(connector); | 224 | radeon_connector = to_radeon_connector(connector); |
205 | if (radeon_encoder->devices & radeon_connector->devices) | 225 | if (radeon_encoder->active_device & radeon_connector->devices) |
206 | return connector; | 226 | return connector; |
207 | } | 227 | } |
208 | return NULL; | 228 | return NULL; |
@@ -596,21 +616,23 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) | |||
596 | return ATOM_ENCODER_MODE_LVDS; | 616 | return ATOM_ENCODER_MODE_LVDS; |
597 | break; | 617 | break; |
598 | case DRM_MODE_CONNECTOR_DisplayPort: | 618 | case DRM_MODE_CONNECTOR_DisplayPort: |
619 | case DRM_MODE_CONNECTOR_eDP: | ||
599 | radeon_dig_connector = radeon_connector->con_priv; | 620 | radeon_dig_connector = radeon_connector->con_priv; |
600 | if (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) | 621 | if ((radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || |
622 | (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) | ||
601 | return ATOM_ENCODER_MODE_DP; | 623 | return ATOM_ENCODER_MODE_DP; |
602 | else if (drm_detect_hdmi_monitor(radeon_connector->edid)) | 624 | else if (drm_detect_hdmi_monitor(radeon_connector->edid)) |
603 | return ATOM_ENCODER_MODE_HDMI; | 625 | return ATOM_ENCODER_MODE_HDMI; |
604 | else | 626 | else |
605 | return ATOM_ENCODER_MODE_DVI; | 627 | return ATOM_ENCODER_MODE_DVI; |
606 | break; | 628 | break; |
607 | case CONNECTOR_DVI_A: | 629 | case DRM_MODE_CONNECTOR_DVIA: |
608 | case CONNECTOR_VGA: | 630 | case DRM_MODE_CONNECTOR_VGA: |
609 | return ATOM_ENCODER_MODE_CRT; | 631 | return ATOM_ENCODER_MODE_CRT; |
610 | break; | 632 | break; |
611 | case CONNECTOR_STV: | 633 | case DRM_MODE_CONNECTOR_Composite: |
612 | case CONNECTOR_CTV: | 634 | case DRM_MODE_CONNECTOR_SVIDEO: |
613 | case CONNECTOR_DIN: | 635 | case DRM_MODE_CONNECTOR_9PinDIN: |
614 | /* fix me */ | 636 | /* fix me */ |
615 | return ATOM_ENCODER_MODE_TV; | 637 | return ATOM_ENCODER_MODE_TV; |
616 | /*return ATOM_ENCODER_MODE_CV;*/ | 638 | /*return ATOM_ENCODER_MODE_CV;*/ |
@@ -674,31 +696,11 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action) | |||
674 | 696 | ||
675 | memset(&args, 0, sizeof(args)); | 697 | memset(&args, 0, sizeof(args)); |
676 | 698 | ||
677 | if (ASIC_IS_DCE32(rdev)) { | 699 | if (dig->dig_encoder) |
678 | if (dig->dig_block) | 700 | index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl); |
679 | index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl); | 701 | else |
680 | else | 702 | index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl); |
681 | index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl); | 703 | num = dig->dig_encoder + 1; |
682 | num = dig->dig_block + 1; | ||
683 | } else { | ||
684 | switch (radeon_encoder->encoder_id) { | ||
685 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: | ||
686 | /* XXX doesn't really matter which dig encoder we pick as long as it's | ||
687 | * not already in use | ||
688 | */ | ||
689 | if (dig_connector->linkb) | ||
690 | index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl); | ||
691 | else | ||
692 | index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl); | ||
693 | num = 1; | ||
694 | break; | ||
695 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: | ||
696 | /* Only dig2 encoder can drive LVTMA */ | ||
697 | index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl); | ||
698 | num = 2; | ||
699 | break; | ||
700 | } | ||
701 | } | ||
702 | 704 | ||
703 | 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); |
704 | 706 | ||
@@ -820,7 +822,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t | |||
820 | args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); | 822 | args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); |
821 | } | 823 | } |
822 | if (ASIC_IS_DCE32(rdev)) { | 824 | if (ASIC_IS_DCE32(rdev)) { |
823 | if (dig->dig_block) | 825 | if (dig->dig_encoder == 1) |
824 | args.v2.acConfig.ucEncoderSel = 1; | 826 | args.v2.acConfig.ucEncoderSel = 1; |
825 | if (dig_connector->linkb) | 827 | if (dig_connector->linkb) |
826 | args.v2.acConfig.ucLinkSel = 1; | 828 | args.v2.acConfig.ucLinkSel = 1; |
@@ -847,17 +849,16 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t | |||
847 | args.v2.acConfig.fCoherentMode = 1; | 849 | args.v2.acConfig.fCoherentMode = 1; |
848 | } | 850 | } |
849 | } else { | 851 | } else { |
852 | |||
850 | args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL; | 853 | args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL; |
851 | 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 | |||
852 | switch (radeon_encoder->encoder_id) { | 860 | switch (radeon_encoder->encoder_id) { |
853 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: | 861 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: |
854 | /* XXX doesn't really matter which dig encoder we pick as long as it's | ||
855 | * not already in use | ||
856 | */ | ||
857 | if (dig_connector->linkb) | ||
858 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER; | ||
859 | else | ||
860 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER; | ||
861 | if (rdev->flags & RADEON_IS_IGP) { | 862 | if (rdev->flags & RADEON_IS_IGP) { |
862 | if (radeon_encoder->pixel_clock > 165000) { | 863 | if (radeon_encoder->pixel_clock > 165000) { |
863 | if (dig_connector->igp_lane_info & 0x3) | 864 | if (dig_connector->igp_lane_info & 0x3) |
@@ -876,10 +877,6 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t | |||
876 | } | 877 | } |
877 | } | 878 | } |
878 | break; | 879 | break; |
879 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: | ||
880 | /* Only dig2 encoder can drive LVTMA */ | ||
881 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER; | ||
882 | break; | ||
883 | } | 880 | } |
884 | 881 | ||
885 | if (radeon_encoder->pixel_clock > 165000) | 882 | if (radeon_encoder->pixel_clock > 165000) |
@@ -1044,6 +1041,7 @@ atombios_set_encoder_crtc_source(struct drm_encoder *encoder) | |||
1044 | union crtc_sourc_param args; | 1041 | union crtc_sourc_param args; |
1045 | int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source); | 1042 | int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source); |
1046 | uint8_t frev, crev; | 1043 | uint8_t frev, crev; |
1044 | struct radeon_encoder_atom_dig *dig; | ||
1047 | 1045 | ||
1048 | memset(&args, 0, sizeof(args)); | 1046 | memset(&args, 0, sizeof(args)); |
1049 | 1047 | ||
@@ -1107,40 +1105,16 @@ atombios_set_encoder_crtc_source(struct drm_encoder *encoder) | |||
1107 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: | 1105 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: |
1108 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: | 1106 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: |
1109 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: | 1107 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: |
1110 | if (ASIC_IS_DCE32(rdev)) { | 1108 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: |
1111 | if (radeon_crtc->crtc_id) | 1109 | dig = radeon_encoder->enc_priv; |
1112 | args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID; | 1110 | if (dig->dig_encoder) |
1113 | else | 1111 | args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID; |
1114 | args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID; | 1112 | else |
1115 | } else { | 1113 | args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID; |
1116 | struct drm_connector *connector; | ||
1117 | struct radeon_connector *radeon_connector; | ||
1118 | struct radeon_connector_atom_dig *dig_connector; | ||
1119 | |||
1120 | connector = radeon_get_connector_for_encoder(encoder); | ||
1121 | if (!connector) | ||
1122 | return; | ||
1123 | radeon_connector = to_radeon_connector(connector); | ||
1124 | if (!radeon_connector->con_priv) | ||
1125 | return; | ||
1126 | dig_connector = radeon_connector->con_priv; | ||
1127 | |||
1128 | /* XXX doesn't really matter which dig encoder we pick as long as it's | ||
1129 | * not already in use | ||
1130 | */ | ||
1131 | if (dig_connector->linkb) | ||
1132 | args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID; | ||
1133 | else | ||
1134 | args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID; | ||
1135 | } | ||
1136 | break; | 1114 | break; |
1137 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: | 1115 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: |
1138 | args.v2.ucEncoderID = ASIC_INT_DVO_ENCODER_ID; | 1116 | args.v2.ucEncoderID = ASIC_INT_DVO_ENCODER_ID; |
1139 | break; | 1117 | break; |
1140 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: | ||
1141 | /* Only dig2 encoder can drive LVTMA */ | ||
1142 | args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID; | ||
1143 | break; | ||
1144 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: | 1118 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: |
1145 | if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) | 1119 | if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) |
1146 | args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; | 1120 | args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; |
@@ -1200,6 +1174,47 @@ atombios_apply_encoder_quirks(struct drm_encoder *encoder, | |||
1200 | } | 1174 | } |
1201 | } | 1175 | } |
1202 | 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 | |||
1203 | static void | 1218 | static void |
1204 | radeon_atom_encoder_mode_set(struct drm_encoder *encoder, | 1219 | radeon_atom_encoder_mode_set(struct drm_encoder *encoder, |
1205 | struct drm_display_mode *mode, | 1220 | struct drm_display_mode *mode, |
@@ -1212,12 +1227,9 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder, | |||
1212 | 1227 | ||
1213 | if (radeon_encoder->active_device & | 1228 | if (radeon_encoder->active_device & |
1214 | (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) { | 1229 | (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) { |
1215 | if (radeon_encoder->enc_priv) { | 1230 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
1216 | struct radeon_encoder_atom_dig *dig; | 1231 | if (dig) |
1217 | 1232 | dig->dig_encoder = radeon_atom_pick_dig_encoder(encoder); | |
1218 | dig = radeon_encoder->enc_priv; | ||
1219 | dig->dig_block = radeon_crtc->crtc_id; | ||
1220 | } | ||
1221 | } | 1233 | } |
1222 | radeon_encoder->pixel_clock = adjusted_mode->clock; | 1234 | radeon_encoder->pixel_clock = adjusted_mode->clock; |
1223 | 1235 | ||
@@ -1377,7 +1389,13 @@ static void radeon_atom_encoder_commit(struct drm_encoder *encoder) | |||
1377 | static void radeon_atom_encoder_disable(struct drm_encoder *encoder) | 1389 | static void radeon_atom_encoder_disable(struct drm_encoder *encoder) |
1378 | { | 1390 | { |
1379 | 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; | ||
1380 | 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 | } | ||
1381 | radeon_encoder->active_device = 0; | 1399 | radeon_encoder->active_device = 0; |
1382 | } | 1400 | } |
1383 | 1401 | ||
@@ -1434,6 +1452,7 @@ radeon_atombios_set_dig_info(struct radeon_encoder *radeon_encoder) | |||
1434 | 1452 | ||
1435 | /* coherent mode by default */ | 1453 | /* coherent mode by default */ |
1436 | dig->coherent_mode = true; | 1454 | dig->coherent_mode = true; |
1455 | dig->dig_encoder = -1; | ||
1437 | 1456 | ||
1438 | return dig; | 1457 | return dig; |
1439 | } | 1458 | } |