diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_encoders.c')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_encoders.c | 382 |
1 files changed, 334 insertions, 48 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index ae58b6849a2e..041943df966b 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c | |||
@@ -176,6 +176,7 @@ static inline bool radeon_encoder_is_digital(struct drm_encoder *encoder) | |||
176 | return false; | 176 | return false; |
177 | } | 177 | } |
178 | } | 178 | } |
179 | |||
179 | void | 180 | void |
180 | radeon_link_encoder_connector(struct drm_device *dev) | 181 | radeon_link_encoder_connector(struct drm_device *dev) |
181 | { | 182 | { |
@@ -228,6 +229,27 @@ radeon_get_connector_for_encoder(struct drm_encoder *encoder) | |||
228 | return NULL; | 229 | return NULL; |
229 | } | 230 | } |
230 | 231 | ||
232 | struct drm_encoder *radeon_atom_get_external_encoder(struct drm_encoder *encoder) | ||
233 | { | ||
234 | struct drm_device *dev = encoder->dev; | ||
235 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
236 | struct drm_encoder *other_encoder; | ||
237 | struct radeon_encoder *other_radeon_encoder; | ||
238 | |||
239 | if (radeon_encoder->is_ext_encoder) | ||
240 | return NULL; | ||
241 | |||
242 | list_for_each_entry(other_encoder, &dev->mode_config.encoder_list, head) { | ||
243 | if (other_encoder == encoder) | ||
244 | continue; | ||
245 | other_radeon_encoder = to_radeon_encoder(other_encoder); | ||
246 | if (other_radeon_encoder->is_ext_encoder && | ||
247 | (radeon_encoder->devices & other_radeon_encoder->devices)) | ||
248 | return other_encoder; | ||
249 | } | ||
250 | return NULL; | ||
251 | } | ||
252 | |||
231 | void radeon_panel_mode_fixup(struct drm_encoder *encoder, | 253 | void radeon_panel_mode_fixup(struct drm_encoder *encoder, |
232 | struct drm_display_mode *adjusted_mode) | 254 | struct drm_display_mode *adjusted_mode) |
233 | { | 255 | { |
@@ -426,52 +448,49 @@ atombios_tv_setup(struct drm_encoder *encoder, int action) | |||
426 | 448 | ||
427 | } | 449 | } |
428 | 450 | ||
429 | void | 451 | union dvo_encoder_control { |
430 | atombios_external_tmds_setup(struct drm_encoder *encoder, int action) | 452 | ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION ext_tmds; |
431 | { | 453 | DVO_ENCODER_CONTROL_PS_ALLOCATION dvo; |
432 | struct drm_device *dev = encoder->dev; | 454 | DVO_ENCODER_CONTROL_PS_ALLOCATION_V3 dvo_v3; |
433 | struct radeon_device *rdev = dev->dev_private; | 455 | }; |
434 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
435 | ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION args; | ||
436 | int index = 0; | ||
437 | |||
438 | memset(&args, 0, sizeof(args)); | ||
439 | |||
440 | index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl); | ||
441 | |||
442 | args.sXTmdsEncoder.ucEnable = action; | ||
443 | |||
444 | if (radeon_encoder->pixel_clock > 165000) | ||
445 | args.sXTmdsEncoder.ucMisc = PANEL_ENCODER_MISC_DUAL; | ||
446 | |||
447 | /*if (pScrn->rgbBits == 8)*/ | ||
448 | args.sXTmdsEncoder.ucMisc |= (1 << 1); | ||
449 | |||
450 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | ||
451 | |||
452 | } | ||
453 | 456 | ||
454 | static void | 457 | void |
455 | atombios_ddia_setup(struct drm_encoder *encoder, int action) | 458 | atombios_dvo_setup(struct drm_encoder *encoder, int action) |
456 | { | 459 | { |
457 | struct drm_device *dev = encoder->dev; | 460 | struct drm_device *dev = encoder->dev; |
458 | struct radeon_device *rdev = dev->dev_private; | 461 | struct radeon_device *rdev = dev->dev_private; |
459 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 462 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
460 | DVO_ENCODER_CONTROL_PS_ALLOCATION args; | 463 | union dvo_encoder_control args; |
461 | int index = 0; | 464 | int index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl); |
462 | 465 | ||
463 | memset(&args, 0, sizeof(args)); | 466 | memset(&args, 0, sizeof(args)); |
464 | 467 | ||
465 | index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl); | 468 | if (ASIC_IS_DCE3(rdev)) { |
469 | /* DCE3+ */ | ||
470 | args.dvo_v3.ucAction = action; | ||
471 | args.dvo_v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); | ||
472 | args.dvo_v3.ucDVOConfig = 0; /* XXX */ | ||
473 | } else if (ASIC_IS_DCE2(rdev)) { | ||
474 | /* DCE2 (pre-DCE3 R6xx, RS600/690/740 */ | ||
475 | args.dvo.sDVOEncoder.ucAction = action; | ||
476 | args.dvo.sDVOEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); | ||
477 | /* DFP1, CRT1, TV1 depending on the type of port */ | ||
478 | args.dvo.sDVOEncoder.ucDeviceType = ATOM_DEVICE_DFP1_INDEX; | ||
479 | |||
480 | if (radeon_encoder->pixel_clock > 165000) | ||
481 | args.dvo.sDVOEncoder.usDevAttr.sDigAttrib.ucAttribute |= PANEL_ENCODER_MISC_DUAL; | ||
482 | } else { | ||
483 | /* R4xx, R5xx */ | ||
484 | args.ext_tmds.sXTmdsEncoder.ucEnable = action; | ||
466 | 485 | ||
467 | args.sDVOEncoder.ucAction = action; | 486 | if (radeon_encoder->pixel_clock > 165000) |
468 | args.sDVOEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); | 487 | args.ext_tmds.sXTmdsEncoder.ucMisc |= PANEL_ENCODER_MISC_DUAL; |
469 | 488 | ||
470 | if (radeon_encoder->pixel_clock > 165000) | 489 | /*if (pScrn->rgbBits == 8)*/ |
471 | args.sDVOEncoder.usDevAttr.sDigAttrib.ucAttribute = PANEL_ENCODER_MISC_DUAL; | 490 | args.ext_tmds.sXTmdsEncoder.ucMisc |= ATOM_PANEL_MISC_888RGB; |
491 | } | ||
472 | 492 | ||
473 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | 493 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
474 | |||
475 | } | 494 | } |
476 | 495 | ||
477 | union lvds_encoder_control { | 496 | union lvds_encoder_control { |
@@ -532,14 +551,14 @@ atombios_digital_setup(struct drm_encoder *encoder, int action) | |||
532 | if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL) | 551 | if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL) |
533 | args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL; | 552 | args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL; |
534 | if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB) | 553 | if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB) |
535 | args.v1.ucMisc |= (1 << 1); | 554 | args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB; |
536 | } else { | 555 | } else { |
537 | if (dig->linkb) | 556 | if (dig->linkb) |
538 | args.v1.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB; | 557 | args.v1.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB; |
539 | if (radeon_encoder->pixel_clock > 165000) | 558 | if (radeon_encoder->pixel_clock > 165000) |
540 | args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL; | 559 | args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL; |
541 | /*if (pScrn->rgbBits == 8) */ | 560 | /*if (pScrn->rgbBits == 8) */ |
542 | args.v1.ucMisc |= (1 << 1); | 561 | args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB; |
543 | } | 562 | } |
544 | break; | 563 | break; |
545 | case 2: | 564 | case 2: |
@@ -595,6 +614,7 @@ atombios_digital_setup(struct drm_encoder *encoder, int action) | |||
595 | int | 614 | int |
596 | atombios_get_encoder_mode(struct drm_encoder *encoder) | 615 | atombios_get_encoder_mode(struct drm_encoder *encoder) |
597 | { | 616 | { |
617 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
598 | struct drm_device *dev = encoder->dev; | 618 | struct drm_device *dev = encoder->dev; |
599 | struct radeon_device *rdev = dev->dev_private; | 619 | struct radeon_device *rdev = dev->dev_private; |
600 | struct drm_connector *connector; | 620 | struct drm_connector *connector; |
@@ -602,9 +622,20 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) | |||
602 | struct radeon_connector_atom_dig *dig_connector; | 622 | struct radeon_connector_atom_dig *dig_connector; |
603 | 623 | ||
604 | connector = radeon_get_connector_for_encoder(encoder); | 624 | connector = radeon_get_connector_for_encoder(encoder); |
605 | if (!connector) | 625 | if (!connector) { |
606 | return 0; | 626 | switch (radeon_encoder->encoder_id) { |
607 | 627 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: | |
628 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: | ||
629 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: | ||
630 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: | ||
631 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: | ||
632 | return ATOM_ENCODER_MODE_DVI; | ||
633 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: | ||
634 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: | ||
635 | default: | ||
636 | return ATOM_ENCODER_MODE_CRT; | ||
637 | } | ||
638 | } | ||
608 | radeon_connector = to_radeon_connector(connector); | 639 | radeon_connector = to_radeon_connector(connector); |
609 | 640 | ||
610 | switch (connector->connector_type) { | 641 | switch (connector->connector_type) { |
@@ -834,6 +865,9 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t | |||
834 | memset(&args, 0, sizeof(args)); | 865 | memset(&args, 0, sizeof(args)); |
835 | 866 | ||
836 | switch (radeon_encoder->encoder_id) { | 867 | switch (radeon_encoder->encoder_id) { |
868 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: | ||
869 | index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl); | ||
870 | break; | ||
837 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: | 871 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: |
838 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: | 872 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: |
839 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: | 873 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: |
@@ -978,6 +1012,105 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t | |||
978 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | 1012 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
979 | } | 1013 | } |
980 | 1014 | ||
1015 | void | ||
1016 | atombios_set_edp_panel_power(struct drm_connector *connector, int action) | ||
1017 | { | ||
1018 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | ||
1019 | struct drm_device *dev = radeon_connector->base.dev; | ||
1020 | struct radeon_device *rdev = dev->dev_private; | ||
1021 | union dig_transmitter_control args; | ||
1022 | int index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl); | ||
1023 | uint8_t frev, crev; | ||
1024 | |||
1025 | if (connector->connector_type != DRM_MODE_CONNECTOR_eDP) | ||
1026 | return; | ||
1027 | |||
1028 | if (!ASIC_IS_DCE4(rdev)) | ||
1029 | return; | ||
1030 | |||
1031 | if ((action != ATOM_TRANSMITTER_ACTION_POWER_ON) || | ||
1032 | (action != ATOM_TRANSMITTER_ACTION_POWER_OFF)) | ||
1033 | return; | ||
1034 | |||
1035 | if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) | ||
1036 | return; | ||
1037 | |||
1038 | memset(&args, 0, sizeof(args)); | ||
1039 | |||
1040 | args.v1.ucAction = action; | ||
1041 | |||
1042 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | ||
1043 | } | ||
1044 | |||
1045 | union external_encoder_control { | ||
1046 | EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION v1; | ||
1047 | }; | ||
1048 | |||
1049 | static void | ||
1050 | atombios_external_encoder_setup(struct drm_encoder *encoder, | ||
1051 | struct drm_encoder *ext_encoder, | ||
1052 | int action) | ||
1053 | { | ||
1054 | struct drm_device *dev = encoder->dev; | ||
1055 | struct radeon_device *rdev = dev->dev_private; | ||
1056 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
1057 | union external_encoder_control args; | ||
1058 | struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); | ||
1059 | int index = GetIndexIntoMasterTable(COMMAND, ExternalEncoderControl); | ||
1060 | u8 frev, crev; | ||
1061 | int dp_clock = 0; | ||
1062 | int dp_lane_count = 0; | ||
1063 | int connector_object_id = 0; | ||
1064 | |||
1065 | if (connector) { | ||
1066 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | ||
1067 | struct radeon_connector_atom_dig *dig_connector = | ||
1068 | radeon_connector->con_priv; | ||
1069 | |||
1070 | dp_clock = dig_connector->dp_clock; | ||
1071 | dp_lane_count = dig_connector->dp_lane_count; | ||
1072 | connector_object_id = | ||
1073 | (radeon_connector->connector_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; | ||
1074 | } | ||
1075 | |||
1076 | memset(&args, 0, sizeof(args)); | ||
1077 | |||
1078 | if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) | ||
1079 | return; | ||
1080 | |||
1081 | switch (frev) { | ||
1082 | case 1: | ||
1083 | /* no params on frev 1 */ | ||
1084 | break; | ||
1085 | case 2: | ||
1086 | switch (crev) { | ||
1087 | case 1: | ||
1088 | case 2: | ||
1089 | args.v1.sDigEncoder.ucAction = action; | ||
1090 | args.v1.sDigEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); | ||
1091 | args.v1.sDigEncoder.ucEncoderMode = atombios_get_encoder_mode(encoder); | ||
1092 | |||
1093 | if (args.v1.sDigEncoder.ucEncoderMode == ATOM_ENCODER_MODE_DP) { | ||
1094 | if (dp_clock == 270000) | ||
1095 | args.v1.sDigEncoder.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ; | ||
1096 | args.v1.sDigEncoder.ucLaneNum = dp_lane_count; | ||
1097 | } else if (radeon_encoder->pixel_clock > 165000) | ||
1098 | args.v1.sDigEncoder.ucLaneNum = 8; | ||
1099 | else | ||
1100 | args.v1.sDigEncoder.ucLaneNum = 4; | ||
1101 | break; | ||
1102 | default: | ||
1103 | DRM_ERROR("Unknown table version: %d, %d\n", frev, crev); | ||
1104 | return; | ||
1105 | } | ||
1106 | break; | ||
1107 | default: | ||
1108 | DRM_ERROR("Unknown table version: %d, %d\n", frev, crev); | ||
1109 | return; | ||
1110 | } | ||
1111 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | ||
1112 | } | ||
1113 | |||
981 | static void | 1114 | static void |
982 | atombios_yuv_setup(struct drm_encoder *encoder, bool enable) | 1115 | atombios_yuv_setup(struct drm_encoder *encoder, bool enable) |
983 | { | 1116 | { |
@@ -1021,6 +1154,7 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode) | |||
1021 | struct drm_device *dev = encoder->dev; | 1154 | struct drm_device *dev = encoder->dev; |
1022 | struct radeon_device *rdev = dev->dev_private; | 1155 | struct radeon_device *rdev = dev->dev_private; |
1023 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 1156 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
1157 | struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder); | ||
1024 | DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args; | 1158 | DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args; |
1025 | int index = 0; | 1159 | int index = 0; |
1026 | bool is_dig = false; | 1160 | bool is_dig = false; |
@@ -1043,9 +1177,14 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode) | |||
1043 | break; | 1177 | break; |
1044 | case ENCODER_OBJECT_ID_INTERNAL_DVO1: | 1178 | case ENCODER_OBJECT_ID_INTERNAL_DVO1: |
1045 | case ENCODER_OBJECT_ID_INTERNAL_DDI: | 1179 | case ENCODER_OBJECT_ID_INTERNAL_DDI: |
1046 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: | ||
1047 | index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl); | 1180 | index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl); |
1048 | break; | 1181 | break; |
1182 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: | ||
1183 | if (ASIC_IS_DCE3(rdev)) | ||
1184 | is_dig = true; | ||
1185 | else | ||
1186 | index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl); | ||
1187 | break; | ||
1049 | case ENCODER_OBJECT_ID_INTERNAL_LVDS: | 1188 | case ENCODER_OBJECT_ID_INTERNAL_LVDS: |
1050 | index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl); | 1189 | index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl); |
1051 | break; | 1190 | break; |
@@ -1082,34 +1221,85 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode) | |||
1082 | if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) { | 1221 | if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) { |
1083 | struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); | 1222 | struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); |
1084 | 1223 | ||
1224 | if (connector && | ||
1225 | (connector->connector_type == DRM_MODE_CONNECTOR_eDP)) { | ||
1226 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | ||
1227 | struct radeon_connector_atom_dig *radeon_dig_connector = | ||
1228 | radeon_connector->con_priv; | ||
1229 | atombios_set_edp_panel_power(connector, | ||
1230 | ATOM_TRANSMITTER_ACTION_POWER_ON); | ||
1231 | radeon_dig_connector->edp_on = true; | ||
1232 | } | ||
1085 | dp_link_train(encoder, connector); | 1233 | dp_link_train(encoder, connector); |
1086 | if (ASIC_IS_DCE4(rdev)) | 1234 | if (ASIC_IS_DCE4(rdev)) |
1087 | atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON); | 1235 | atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON); |
1088 | } | 1236 | } |
1237 | if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) | ||
1238 | atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0); | ||
1089 | break; | 1239 | break; |
1090 | case DRM_MODE_DPMS_STANDBY: | 1240 | case DRM_MODE_DPMS_STANDBY: |
1091 | case DRM_MODE_DPMS_SUSPEND: | 1241 | case DRM_MODE_DPMS_SUSPEND: |
1092 | case DRM_MODE_DPMS_OFF: | 1242 | case DRM_MODE_DPMS_OFF: |
1093 | atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0); | 1243 | atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0); |
1094 | if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) { | 1244 | if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) { |
1245 | struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); | ||
1246 | |||
1095 | if (ASIC_IS_DCE4(rdev)) | 1247 | if (ASIC_IS_DCE4(rdev)) |
1096 | atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF); | 1248 | atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF); |
1249 | if (connector && | ||
1250 | (connector->connector_type == DRM_MODE_CONNECTOR_eDP)) { | ||
1251 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | ||
1252 | struct radeon_connector_atom_dig *radeon_dig_connector = | ||
1253 | radeon_connector->con_priv; | ||
1254 | atombios_set_edp_panel_power(connector, | ||
1255 | ATOM_TRANSMITTER_ACTION_POWER_OFF); | ||
1256 | radeon_dig_connector->edp_on = false; | ||
1257 | } | ||
1097 | } | 1258 | } |
1259 | if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) | ||
1260 | atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0); | ||
1098 | break; | 1261 | break; |
1099 | } | 1262 | } |
1100 | } else { | 1263 | } else { |
1101 | switch (mode) { | 1264 | switch (mode) { |
1102 | case DRM_MODE_DPMS_ON: | 1265 | case DRM_MODE_DPMS_ON: |
1103 | args.ucAction = ATOM_ENABLE; | 1266 | args.ucAction = ATOM_ENABLE; |
1267 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | ||
1268 | if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { | ||
1269 | args.ucAction = ATOM_LCD_BLON; | ||
1270 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | ||
1271 | } | ||
1104 | break; | 1272 | break; |
1105 | case DRM_MODE_DPMS_STANDBY: | 1273 | case DRM_MODE_DPMS_STANDBY: |
1106 | case DRM_MODE_DPMS_SUSPEND: | 1274 | case DRM_MODE_DPMS_SUSPEND: |
1107 | case DRM_MODE_DPMS_OFF: | 1275 | case DRM_MODE_DPMS_OFF: |
1108 | args.ucAction = ATOM_DISABLE; | 1276 | args.ucAction = ATOM_DISABLE; |
1277 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | ||
1278 | if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { | ||
1279 | args.ucAction = ATOM_LCD_BLOFF; | ||
1280 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | ||
1281 | } | ||
1109 | break; | 1282 | break; |
1110 | } | 1283 | } |
1111 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | ||
1112 | } | 1284 | } |
1285 | |||
1286 | if (ext_encoder) { | ||
1287 | int action; | ||
1288 | |||
1289 | switch (mode) { | ||
1290 | case DRM_MODE_DPMS_ON: | ||
1291 | default: | ||
1292 | action = ATOM_ENABLE; | ||
1293 | break; | ||
1294 | case DRM_MODE_DPMS_STANDBY: | ||
1295 | case DRM_MODE_DPMS_SUSPEND: | ||
1296 | case DRM_MODE_DPMS_OFF: | ||
1297 | action = ATOM_DISABLE; | ||
1298 | break; | ||
1299 | } | ||
1300 | atombios_external_encoder_setup(encoder, ext_encoder, action); | ||
1301 | } | ||
1302 | |||
1113 | radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false); | 1303 | radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false); |
1114 | 1304 | ||
1115 | } | 1305 | } |
@@ -1242,7 +1432,7 @@ atombios_set_encoder_crtc_source(struct drm_encoder *encoder) | |||
1242 | break; | 1432 | break; |
1243 | default: | 1433 | default: |
1244 | DRM_ERROR("Unknown table version: %d, %d\n", frev, crev); | 1434 | DRM_ERROR("Unknown table version: %d, %d\n", frev, crev); |
1245 | break; | 1435 | return; |
1246 | } | 1436 | } |
1247 | 1437 | ||
1248 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | 1438 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
@@ -1357,6 +1547,7 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder, | |||
1357 | struct drm_device *dev = encoder->dev; | 1547 | struct drm_device *dev = encoder->dev; |
1358 | struct radeon_device *rdev = dev->dev_private; | 1548 | struct radeon_device *rdev = dev->dev_private; |
1359 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 1549 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
1550 | struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder); | ||
1360 | 1551 | ||
1361 | radeon_encoder->pixel_clock = adjusted_mode->clock; | 1552 | radeon_encoder->pixel_clock = adjusted_mode->clock; |
1362 | 1553 | ||
@@ -1400,11 +1591,9 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder, | |||
1400 | } | 1591 | } |
1401 | break; | 1592 | break; |
1402 | case ENCODER_OBJECT_ID_INTERNAL_DDI: | 1593 | case ENCODER_OBJECT_ID_INTERNAL_DDI: |
1403 | atombios_ddia_setup(encoder, ATOM_ENABLE); | ||
1404 | break; | ||
1405 | case ENCODER_OBJECT_ID_INTERNAL_DVO1: | 1594 | case ENCODER_OBJECT_ID_INTERNAL_DVO1: |
1406 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: | 1595 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: |
1407 | atombios_external_tmds_setup(encoder, ATOM_ENABLE); | 1596 | atombios_dvo_setup(encoder, ATOM_ENABLE); |
1408 | break; | 1597 | break; |
1409 | case ENCODER_OBJECT_ID_INTERNAL_DAC1: | 1598 | case ENCODER_OBJECT_ID_INTERNAL_DAC1: |
1410 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: | 1599 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: |
@@ -1419,6 +1608,11 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder, | |||
1419 | } | 1608 | } |
1420 | break; | 1609 | break; |
1421 | } | 1610 | } |
1611 | |||
1612 | if (ext_encoder) { | ||
1613 | atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE); | ||
1614 | } | ||
1615 | |||
1422 | atombios_apply_encoder_quirks(encoder, adjusted_mode); | 1616 | atombios_apply_encoder_quirks(encoder, adjusted_mode); |
1423 | 1617 | ||
1424 | if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) { | 1618 | if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) { |
@@ -1520,6 +1714,7 @@ radeon_atom_dac_detect(struct drm_encoder *encoder, struct drm_connector *connec | |||
1520 | static void radeon_atom_encoder_prepare(struct drm_encoder *encoder) | 1714 | static void radeon_atom_encoder_prepare(struct drm_encoder *encoder) |
1521 | { | 1715 | { |
1522 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 1716 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
1717 | struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); | ||
1523 | 1718 | ||
1524 | if (radeon_encoder->active_device & | 1719 | if (radeon_encoder->active_device & |
1525 | (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) { | 1720 | (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) { |
@@ -1531,6 +1726,13 @@ static void radeon_atom_encoder_prepare(struct drm_encoder *encoder) | |||
1531 | radeon_atom_output_lock(encoder, true); | 1726 | radeon_atom_output_lock(encoder, true); |
1532 | radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); | 1727 | radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); |
1533 | 1728 | ||
1729 | /* select the clock/data port if it uses a router */ | ||
1730 | if (connector) { | ||
1731 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | ||
1732 | if (radeon_connector->router.cd_valid) | ||
1733 | radeon_router_select_cd_port(radeon_connector); | ||
1734 | } | ||
1735 | |||
1534 | /* this is needed for the pll/ss setup to work correctly in some cases */ | 1736 | /* this is needed for the pll/ss setup to work correctly in some cases */ |
1535 | atombios_set_encoder_crtc_source(encoder); | 1737 | atombios_set_encoder_crtc_source(encoder); |
1536 | } | 1738 | } |
@@ -1547,6 +1749,23 @@ static void radeon_atom_encoder_disable(struct drm_encoder *encoder) | |||
1547 | struct radeon_device *rdev = dev->dev_private; | 1749 | struct radeon_device *rdev = dev->dev_private; |
1548 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 1750 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
1549 | struct radeon_encoder_atom_dig *dig; | 1751 | struct radeon_encoder_atom_dig *dig; |
1752 | |||
1753 | /* check for pre-DCE3 cards with shared encoders; | ||
1754 | * can't really use the links individually, so don't disable | ||
1755 | * the encoder if it's in use by another connector | ||
1756 | */ | ||
1757 | if (!ASIC_IS_DCE3(rdev)) { | ||
1758 | struct drm_encoder *other_encoder; | ||
1759 | struct radeon_encoder *other_radeon_encoder; | ||
1760 | |||
1761 | list_for_each_entry(other_encoder, &dev->mode_config.encoder_list, head) { | ||
1762 | other_radeon_encoder = to_radeon_encoder(other_encoder); | ||
1763 | if ((radeon_encoder->encoder_id == other_radeon_encoder->encoder_id) && | ||
1764 | drm_helper_encoder_in_use(other_encoder)) | ||
1765 | goto disable_done; | ||
1766 | } | ||
1767 | } | ||
1768 | |||
1550 | radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); | 1769 | radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); |
1551 | 1770 | ||
1552 | switch (radeon_encoder->encoder_id) { | 1771 | switch (radeon_encoder->encoder_id) { |
@@ -1570,11 +1789,9 @@ static void radeon_atom_encoder_disable(struct drm_encoder *encoder) | |||
1570 | } | 1789 | } |
1571 | break; | 1790 | break; |
1572 | case ENCODER_OBJECT_ID_INTERNAL_DDI: | 1791 | case ENCODER_OBJECT_ID_INTERNAL_DDI: |
1573 | atombios_ddia_setup(encoder, ATOM_DISABLE); | ||
1574 | break; | ||
1575 | case ENCODER_OBJECT_ID_INTERNAL_DVO1: | 1792 | case ENCODER_OBJECT_ID_INTERNAL_DVO1: |
1576 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: | 1793 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: |
1577 | atombios_external_tmds_setup(encoder, ATOM_DISABLE); | 1794 | atombios_dvo_setup(encoder, ATOM_DISABLE); |
1578 | break; | 1795 | break; |
1579 | case ENCODER_OBJECT_ID_INTERNAL_DAC1: | 1796 | case ENCODER_OBJECT_ID_INTERNAL_DAC1: |
1580 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: | 1797 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: |
@@ -1586,6 +1803,7 @@ static void radeon_atom_encoder_disable(struct drm_encoder *encoder) | |||
1586 | break; | 1803 | break; |
1587 | } | 1804 | } |
1588 | 1805 | ||
1806 | disable_done: | ||
1589 | if (radeon_encoder_is_digital(encoder)) { | 1807 | if (radeon_encoder_is_digital(encoder)) { |
1590 | if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) | 1808 | if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) |
1591 | r600_hdmi_disable(encoder); | 1809 | r600_hdmi_disable(encoder); |
@@ -1595,6 +1813,53 @@ static void radeon_atom_encoder_disable(struct drm_encoder *encoder) | |||
1595 | radeon_encoder->active_device = 0; | 1813 | radeon_encoder->active_device = 0; |
1596 | } | 1814 | } |
1597 | 1815 | ||
1816 | /* these are handled by the primary encoders */ | ||
1817 | static void radeon_atom_ext_prepare(struct drm_encoder *encoder) | ||
1818 | { | ||
1819 | |||
1820 | } | ||
1821 | |||
1822 | static void radeon_atom_ext_commit(struct drm_encoder *encoder) | ||
1823 | { | ||
1824 | |||
1825 | } | ||
1826 | |||
1827 | static void | ||
1828 | radeon_atom_ext_mode_set(struct drm_encoder *encoder, | ||
1829 | struct drm_display_mode *mode, | ||
1830 | struct drm_display_mode *adjusted_mode) | ||
1831 | { | ||
1832 | |||
1833 | } | ||
1834 | |||
1835 | static void radeon_atom_ext_disable(struct drm_encoder *encoder) | ||
1836 | { | ||
1837 | |||
1838 | } | ||
1839 | |||
1840 | static void | ||
1841 | radeon_atom_ext_dpms(struct drm_encoder *encoder, int mode) | ||
1842 | { | ||
1843 | |||
1844 | } | ||
1845 | |||
1846 | static bool radeon_atom_ext_mode_fixup(struct drm_encoder *encoder, | ||
1847 | struct drm_display_mode *mode, | ||
1848 | struct drm_display_mode *adjusted_mode) | ||
1849 | { | ||
1850 | return true; | ||
1851 | } | ||
1852 | |||
1853 | static const struct drm_encoder_helper_funcs radeon_atom_ext_helper_funcs = { | ||
1854 | .dpms = radeon_atom_ext_dpms, | ||
1855 | .mode_fixup = radeon_atom_ext_mode_fixup, | ||
1856 | .prepare = radeon_atom_ext_prepare, | ||
1857 | .mode_set = radeon_atom_ext_mode_set, | ||
1858 | .commit = radeon_atom_ext_commit, | ||
1859 | .disable = radeon_atom_ext_disable, | ||
1860 | /* no detect for TMDS/LVDS yet */ | ||
1861 | }; | ||
1862 | |||
1598 | static const struct drm_encoder_helper_funcs radeon_atom_dig_helper_funcs = { | 1863 | static const struct drm_encoder_helper_funcs radeon_atom_dig_helper_funcs = { |
1599 | .dpms = radeon_atom_encoder_dpms, | 1864 | .dpms = radeon_atom_encoder_dpms, |
1600 | .mode_fixup = radeon_atom_mode_fixup, | 1865 | .mode_fixup = radeon_atom_mode_fixup, |
@@ -1704,6 +1969,7 @@ radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_enum, uint32_t | |||
1704 | radeon_encoder->devices = supported_device; | 1969 | radeon_encoder->devices = supported_device; |
1705 | radeon_encoder->rmx_type = RMX_OFF; | 1970 | radeon_encoder->rmx_type = RMX_OFF; |
1706 | radeon_encoder->underscan_type = UNDERSCAN_OFF; | 1971 | radeon_encoder->underscan_type = UNDERSCAN_OFF; |
1972 | radeon_encoder->is_ext_encoder = false; | ||
1707 | 1973 | ||
1708 | switch (radeon_encoder->encoder_id) { | 1974 | switch (radeon_encoder->encoder_id) { |
1709 | case ENCODER_OBJECT_ID_INTERNAL_LVDS: | 1975 | case ENCODER_OBJECT_ID_INTERNAL_LVDS: |
@@ -1745,6 +2011,9 @@ radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_enum, uint32_t | |||
1745 | radeon_encoder->rmx_type = RMX_FULL; | 2011 | radeon_encoder->rmx_type = RMX_FULL; |
1746 | drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS); | 2012 | drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS); |
1747 | radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder); | 2013 | radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder); |
2014 | } else if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT)) { | ||
2015 | drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC); | ||
2016 | radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder); | ||
1748 | } else { | 2017 | } else { |
1749 | drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS); | 2018 | drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS); |
1750 | radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder); | 2019 | radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder); |
@@ -1753,5 +2022,22 @@ radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_enum, uint32_t | |||
1753 | } | 2022 | } |
1754 | drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs); | 2023 | drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs); |
1755 | break; | 2024 | break; |
2025 | case ENCODER_OBJECT_ID_SI170B: | ||
2026 | case ENCODER_OBJECT_ID_CH7303: | ||
2027 | case ENCODER_OBJECT_ID_EXTERNAL_SDVOA: | ||
2028 | case ENCODER_OBJECT_ID_EXTERNAL_SDVOB: | ||
2029 | case ENCODER_OBJECT_ID_TITFP513: | ||
2030 | case ENCODER_OBJECT_ID_VT1623: | ||
2031 | case ENCODER_OBJECT_ID_HDMI_SI1930: | ||
2032 | /* these are handled by the primary encoders */ | ||
2033 | radeon_encoder->is_ext_encoder = true; | ||
2034 | if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) | ||
2035 | drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS); | ||
2036 | else if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT)) | ||
2037 | drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC); | ||
2038 | else | ||
2039 | drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS); | ||
2040 | drm_encoder_helper_add(encoder, &radeon_atom_ext_helper_funcs); | ||
2041 | break; | ||
1756 | } | 2042 | } |
1757 | } | 2043 | } |