diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_encoders.c')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_encoders.c | 121 |
1 files changed, 64 insertions, 57 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index bc926ea0a53..52d6f96f274 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c | |||
@@ -302,7 +302,7 @@ static bool radeon_atom_mode_fixup(struct drm_encoder *encoder, | |||
302 | } | 302 | } |
303 | 303 | ||
304 | if (ASIC_IS_DCE3(rdev) && | 304 | if (ASIC_IS_DCE3(rdev) && |
305 | (radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT))) { | 305 | (radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT))) { |
306 | struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); | 306 | struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); |
307 | radeon_dp_set_link_config(connector, mode); | 307 | radeon_dp_set_link_config(connector, mode); |
308 | } | 308 | } |
@@ -519,7 +519,8 @@ atombios_digital_setup(struct drm_encoder *encoder, int action) | |||
519 | break; | 519 | break; |
520 | } | 520 | } |
521 | 521 | ||
522 | atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev); | 522 | if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) |
523 | return; | ||
523 | 524 | ||
524 | switch (frev) { | 525 | switch (frev) { |
525 | case 1: | 526 | case 1: |
@@ -593,7 +594,6 @@ atombios_digital_setup(struct drm_encoder *encoder, int action) | |||
593 | } | 594 | } |
594 | 595 | ||
595 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | 596 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
596 | r600_hdmi_enable(encoder, hdmi_detected); | ||
597 | } | 597 | } |
598 | 598 | ||
599 | int | 599 | int |
@@ -708,7 +708,7 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action) | |||
708 | struct radeon_connector_atom_dig *dig_connector = | 708 | struct radeon_connector_atom_dig *dig_connector = |
709 | radeon_get_atom_connector_priv_from_encoder(encoder); | 709 | radeon_get_atom_connector_priv_from_encoder(encoder); |
710 | union dig_encoder_control args; | 710 | union dig_encoder_control args; |
711 | int index = 0, num = 0; | 711 | int index = 0; |
712 | uint8_t frev, crev; | 712 | uint8_t frev, crev; |
713 | 713 | ||
714 | if (!dig || !dig_connector) | 714 | if (!dig || !dig_connector) |
@@ -724,9 +724,9 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action) | |||
724 | else | 724 | else |
725 | index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl); | 725 | index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl); |
726 | } | 726 | } |
727 | num = dig->dig_encoder + 1; | ||
728 | 727 | ||
729 | atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev); | 728 | if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) |
729 | return; | ||
730 | 730 | ||
731 | args.v1.ucAction = action; | 731 | args.v1.ucAction = action; |
732 | args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); | 732 | args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); |
@@ -785,7 +785,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t | |||
785 | struct drm_connector *connector; | 785 | struct drm_connector *connector; |
786 | struct radeon_connector *radeon_connector; | 786 | struct radeon_connector *radeon_connector; |
787 | union dig_transmitter_control args; | 787 | union dig_transmitter_control args; |
788 | int index = 0, num = 0; | 788 | int index = 0; |
789 | uint8_t frev, crev; | 789 | uint8_t frev, crev; |
790 | bool is_dp = false; | 790 | bool is_dp = false; |
791 | int pll_id = 0; | 791 | int pll_id = 0; |
@@ -814,7 +814,8 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t | |||
814 | } | 814 | } |
815 | } | 815 | } |
816 | 816 | ||
817 | atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev); | 817 | if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) |
818 | return; | ||
818 | 819 | ||
819 | args.v1.ucAction = action; | 820 | args.v1.ucAction = action; |
820 | if (action == ATOM_TRANSMITTER_ACTION_INIT) { | 821 | if (action == ATOM_TRANSMITTER_ACTION_INIT) { |
@@ -860,15 +861,12 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t | |||
860 | switch (radeon_encoder->encoder_id) { | 861 | switch (radeon_encoder->encoder_id) { |
861 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: | 862 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: |
862 | args.v3.acConfig.ucTransmitterSel = 0; | 863 | args.v3.acConfig.ucTransmitterSel = 0; |
863 | num = 0; | ||
864 | break; | 864 | break; |
865 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: | 865 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: |
866 | args.v3.acConfig.ucTransmitterSel = 1; | 866 | args.v3.acConfig.ucTransmitterSel = 1; |
867 | num = 1; | ||
868 | break; | 867 | break; |
869 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: | 868 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: |
870 | args.v3.acConfig.ucTransmitterSel = 2; | 869 | args.v3.acConfig.ucTransmitterSel = 2; |
871 | num = 2; | ||
872 | break; | 870 | break; |
873 | } | 871 | } |
874 | 872 | ||
@@ -879,23 +877,19 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t | |||
879 | args.v3.acConfig.fCoherentMode = 1; | 877 | args.v3.acConfig.fCoherentMode = 1; |
880 | } | 878 | } |
881 | } else if (ASIC_IS_DCE32(rdev)) { | 879 | } else if (ASIC_IS_DCE32(rdev)) { |
882 | if (dig->dig_encoder == 1) | 880 | args.v2.acConfig.ucEncoderSel = dig->dig_encoder; |
883 | args.v2.acConfig.ucEncoderSel = 1; | ||
884 | if (dig_connector->linkb) | 881 | if (dig_connector->linkb) |
885 | args.v2.acConfig.ucLinkSel = 1; | 882 | args.v2.acConfig.ucLinkSel = 1; |
886 | 883 | ||
887 | switch (radeon_encoder->encoder_id) { | 884 | switch (radeon_encoder->encoder_id) { |
888 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: | 885 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: |
889 | args.v2.acConfig.ucTransmitterSel = 0; | 886 | args.v2.acConfig.ucTransmitterSel = 0; |
890 | num = 0; | ||
891 | break; | 887 | break; |
892 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: | 888 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: |
893 | args.v2.acConfig.ucTransmitterSel = 1; | 889 | args.v2.acConfig.ucTransmitterSel = 1; |
894 | num = 1; | ||
895 | break; | 890 | break; |
896 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: | 891 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: |
897 | args.v2.acConfig.ucTransmitterSel = 2; | 892 | args.v2.acConfig.ucTransmitterSel = 2; |
898 | num = 2; | ||
899 | break; | 893 | break; |
900 | } | 894 | } |
901 | 895 | ||
@@ -913,31 +907,25 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t | |||
913 | else | 907 | else |
914 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER; | 908 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER; |
915 | 909 | ||
916 | switch (radeon_encoder->encoder_id) { | 910 | if ((rdev->flags & RADEON_IS_IGP) && |
917 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: | 911 | (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_UNIPHY)) { |
918 | if (rdev->flags & RADEON_IS_IGP) { | 912 | if (is_dp || (radeon_encoder->pixel_clock <= 165000)) { |
919 | if (radeon_encoder->pixel_clock > 165000) { | 913 | if (dig_connector->igp_lane_info & 0x1) |
920 | if (dig_connector->igp_lane_info & 0x3) | 914 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3; |
921 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7; | 915 | else if (dig_connector->igp_lane_info & 0x2) |
922 | else if (dig_connector->igp_lane_info & 0xc) | 916 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_4_7; |
923 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15; | 917 | else if (dig_connector->igp_lane_info & 0x4) |
924 | } else { | 918 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_11; |
925 | if (dig_connector->igp_lane_info & 0x1) | 919 | else if (dig_connector->igp_lane_info & 0x8) |
926 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3; | 920 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15; |
927 | else if (dig_connector->igp_lane_info & 0x2) | 921 | } else { |
928 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_4_7; | 922 | if (dig_connector->igp_lane_info & 0x3) |
929 | else if (dig_connector->igp_lane_info & 0x4) | 923 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7; |
930 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_11; | 924 | else if (dig_connector->igp_lane_info & 0xc) |
931 | else if (dig_connector->igp_lane_info & 0x8) | 925 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15; |
932 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15; | ||
933 | } | ||
934 | } | 926 | } |
935 | break; | ||
936 | } | 927 | } |
937 | 928 | ||
938 | if (radeon_encoder->pixel_clock > 165000) | ||
939 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK; | ||
940 | |||
941 | if (dig_connector->linkb) | 929 | if (dig_connector->linkb) |
942 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB; | 930 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB; |
943 | else | 931 | else |
@@ -948,6 +936,8 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t | |||
948 | else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { | 936 | else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { |
949 | if (dig->coherent_mode) | 937 | if (dig->coherent_mode) |
950 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT; | 938 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT; |
939 | if (radeon_encoder->pixel_clock > 165000) | ||
940 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK; | ||
951 | } | 941 | } |
952 | } | 942 | } |
953 | 943 | ||
@@ -1054,16 +1044,25 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode) | |||
1054 | if (is_dig) { | 1044 | if (is_dig) { |
1055 | switch (mode) { | 1045 | switch (mode) { |
1056 | case DRM_MODE_DPMS_ON: | 1046 | case DRM_MODE_DPMS_ON: |
1057 | atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); | 1047 | if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) { |
1058 | { | ||
1059 | struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); | 1048 | struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); |
1049 | |||
1060 | dp_link_train(encoder, connector); | 1050 | dp_link_train(encoder, connector); |
1051 | if (ASIC_IS_DCE4(rdev)) | ||
1052 | atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON); | ||
1061 | } | 1053 | } |
1054 | if (!ASIC_IS_DCE4(rdev)) | ||
1055 | atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); | ||
1062 | break; | 1056 | break; |
1063 | case DRM_MODE_DPMS_STANDBY: | 1057 | case DRM_MODE_DPMS_STANDBY: |
1064 | case DRM_MODE_DPMS_SUSPEND: | 1058 | case DRM_MODE_DPMS_SUSPEND: |
1065 | case DRM_MODE_DPMS_OFF: | 1059 | case DRM_MODE_DPMS_OFF: |
1066 | atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0); | 1060 | if (!ASIC_IS_DCE4(rdev)) |
1061 | atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0); | ||
1062 | if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) { | ||
1063 | if (ASIC_IS_DCE4(rdev)) | ||
1064 | atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF); | ||
1065 | } | ||
1067 | break; | 1066 | break; |
1068 | } | 1067 | } |
1069 | } else { | 1068 | } else { |
@@ -1104,7 +1103,8 @@ atombios_set_encoder_crtc_source(struct drm_encoder *encoder) | |||
1104 | 1103 | ||
1105 | memset(&args, 0, sizeof(args)); | 1104 | memset(&args, 0, sizeof(args)); |
1106 | 1105 | ||
1107 | atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev); | 1106 | if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) |
1107 | return; | ||
1108 | 1108 | ||
1109 | switch (frev) { | 1109 | switch (frev) { |
1110 | case 1: | 1110 | case 1: |
@@ -1216,6 +1216,9 @@ atombios_set_encoder_crtc_source(struct drm_encoder *encoder) | |||
1216 | } | 1216 | } |
1217 | 1217 | ||
1218 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | 1218 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
1219 | |||
1220 | /* update scratch regs with new routing */ | ||
1221 | radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); | ||
1219 | } | 1222 | } |
1220 | 1223 | ||
1221 | static void | 1224 | static void |
@@ -1326,19 +1329,9 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder, | |||
1326 | struct drm_device *dev = encoder->dev; | 1329 | struct drm_device *dev = encoder->dev; |
1327 | struct radeon_device *rdev = dev->dev_private; | 1330 | struct radeon_device *rdev = dev->dev_private; |
1328 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 1331 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
1329 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); | ||
1330 | 1332 | ||
1331 | if (radeon_encoder->active_device & | ||
1332 | (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) { | ||
1333 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | ||
1334 | if (dig) | ||
1335 | dig->dig_encoder = radeon_atom_pick_dig_encoder(encoder); | ||
1336 | } | ||
1337 | radeon_encoder->pixel_clock = adjusted_mode->clock; | 1333 | radeon_encoder->pixel_clock = adjusted_mode->clock; |
1338 | 1334 | ||
1339 | radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); | ||
1340 | atombios_set_encoder_crtc_source(encoder); | ||
1341 | |||
1342 | if (ASIC_IS_AVIVO(rdev)) { | 1335 | if (ASIC_IS_AVIVO(rdev)) { |
1343 | if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT)) | 1336 | if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT)) |
1344 | atombios_yuv_setup(encoder, true); | 1337 | atombios_yuv_setup(encoder, true); |
@@ -1396,9 +1389,10 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder, | |||
1396 | } | 1389 | } |
1397 | atombios_apply_encoder_quirks(encoder, adjusted_mode); | 1390 | atombios_apply_encoder_quirks(encoder, adjusted_mode); |
1398 | 1391 | ||
1399 | /* XXX */ | 1392 | if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) { |
1400 | if (!ASIC_IS_DCE4(rdev)) | 1393 | r600_hdmi_enable(encoder); |
1401 | r600_hdmi_setmode(encoder, adjusted_mode); | 1394 | r600_hdmi_setmode(encoder, adjusted_mode); |
1395 | } | ||
1402 | } | 1396 | } |
1403 | 1397 | ||
1404 | static bool | 1398 | static bool |
@@ -1418,7 +1412,8 @@ atombios_dac_load_detect(struct drm_encoder *encoder, struct drm_connector *conn | |||
1418 | 1412 | ||
1419 | memset(&args, 0, sizeof(args)); | 1413 | memset(&args, 0, sizeof(args)); |
1420 | 1414 | ||
1421 | atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev); | 1415 | if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) |
1416 | return false; | ||
1422 | 1417 | ||
1423 | args.sDacload.ucMisc = 0; | 1418 | args.sDacload.ucMisc = 0; |
1424 | 1419 | ||
@@ -1492,8 +1487,20 @@ radeon_atom_dac_detect(struct drm_encoder *encoder, struct drm_connector *connec | |||
1492 | 1487 | ||
1493 | static void radeon_atom_encoder_prepare(struct drm_encoder *encoder) | 1488 | static void radeon_atom_encoder_prepare(struct drm_encoder *encoder) |
1494 | { | 1489 | { |
1490 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
1491 | |||
1492 | if (radeon_encoder->active_device & | ||
1493 | (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) { | ||
1494 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | ||
1495 | if (dig) | ||
1496 | dig->dig_encoder = radeon_atom_pick_dig_encoder(encoder); | ||
1497 | } | ||
1498 | |||
1495 | radeon_atom_output_lock(encoder, true); | 1499 | radeon_atom_output_lock(encoder, true); |
1496 | radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); | 1500 | radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); |
1501 | |||
1502 | /* this is needed for the pll/ss setup to work correctly in some cases */ | ||
1503 | atombios_set_encoder_crtc_source(encoder); | ||
1497 | } | 1504 | } |
1498 | 1505 | ||
1499 | static void radeon_atom_encoder_commit(struct drm_encoder *encoder) | 1506 | static void radeon_atom_encoder_commit(struct drm_encoder *encoder) |
@@ -1509,6 +1516,8 @@ static void radeon_atom_encoder_disable(struct drm_encoder *encoder) | |||
1509 | radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); | 1516 | radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); |
1510 | 1517 | ||
1511 | if (radeon_encoder_is_digital(encoder)) { | 1518 | if (radeon_encoder_is_digital(encoder)) { |
1519 | if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) | ||
1520 | r600_hdmi_disable(encoder); | ||
1512 | dig = radeon_encoder->enc_priv; | 1521 | dig = radeon_encoder->enc_priv; |
1513 | dig->dig_encoder = -1; | 1522 | dig->dig_encoder = -1; |
1514 | } | 1523 | } |
@@ -1659,6 +1668,4 @@ radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t su | |||
1659 | drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs); | 1668 | drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs); |
1660 | break; | 1669 | break; |
1661 | } | 1670 | } |
1662 | |||
1663 | r600_hdmi_init(encoder); | ||
1664 | } | 1671 | } |