diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_encoders.c')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_encoders.c | 140 |
1 files changed, 104 insertions, 36 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index 1b557554696e..b293487e5aa3 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c | |||
@@ -367,7 +367,8 @@ static bool radeon_atom_mode_fixup(struct drm_encoder *encoder, | |||
367 | } | 367 | } |
368 | 368 | ||
369 | if (ASIC_IS_DCE3(rdev) && | 369 | if (ASIC_IS_DCE3(rdev) && |
370 | (radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT))) { | 370 | ((radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) || |
371 | radeon_encoder_is_dp_bridge(encoder))) { | ||
371 | struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); | 372 | struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); |
372 | radeon_dp_set_link_config(connector, mode); | 373 | radeon_dp_set_link_config(connector, mode); |
373 | } | 374 | } |
@@ -660,21 +661,16 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) | |||
660 | if (radeon_encoder_is_dp_bridge(encoder)) | 661 | if (radeon_encoder_is_dp_bridge(encoder)) |
661 | return ATOM_ENCODER_MODE_DP; | 662 | return ATOM_ENCODER_MODE_DP; |
662 | 663 | ||
664 | /* DVO is always DVO */ | ||
665 | if (radeon_encoder->encoder_id == ATOM_ENCODER_MODE_DVO) | ||
666 | return ATOM_ENCODER_MODE_DVO; | ||
667 | |||
663 | connector = radeon_get_connector_for_encoder(encoder); | 668 | connector = radeon_get_connector_for_encoder(encoder); |
664 | if (!connector) { | 669 | /* if we don't have an active device yet, just use one of |
665 | switch (radeon_encoder->encoder_id) { | 670 | * the connectors tied to the encoder. |
666 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: | 671 | */ |
667 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: | 672 | if (!connector) |
668 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: | 673 | connector = radeon_get_connector_for_encoder_init(encoder); |
669 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: | ||
670 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: | ||
671 | return ATOM_ENCODER_MODE_DVI; | ||
672 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: | ||
673 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: | ||
674 | default: | ||
675 | return ATOM_ENCODER_MODE_CRT; | ||
676 | } | ||
677 | } | ||
678 | radeon_connector = to_radeon_connector(connector); | 674 | radeon_connector = to_radeon_connector(connector); |
679 | 675 | ||
680 | switch (connector->connector_type) { | 676 | switch (connector->connector_type) { |
@@ -954,10 +950,15 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t | |||
954 | int dp_lane_count = 0; | 950 | int dp_lane_count = 0; |
955 | int connector_object_id = 0; | 951 | int connector_object_id = 0; |
956 | int igp_lane_info = 0; | 952 | int igp_lane_info = 0; |
953 | int dig_encoder = dig->dig_encoder; | ||
957 | 954 | ||
958 | if (action == ATOM_TRANSMITTER_ACTION_INIT) | 955 | if (action == ATOM_TRANSMITTER_ACTION_INIT) { |
959 | connector = radeon_get_connector_for_encoder_init(encoder); | 956 | connector = radeon_get_connector_for_encoder_init(encoder); |
960 | else | 957 | /* just needed to avoid bailing in the encoder check. the encoder |
958 | * isn't used for init | ||
959 | */ | ||
960 | dig_encoder = 0; | ||
961 | } else | ||
961 | connector = radeon_get_connector_for_encoder(encoder); | 962 | connector = radeon_get_connector_for_encoder(encoder); |
962 | 963 | ||
963 | if (connector) { | 964 | if (connector) { |
@@ -973,7 +974,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t | |||
973 | } | 974 | } |
974 | 975 | ||
975 | /* no dig encoder assigned */ | 976 | /* no dig encoder assigned */ |
976 | if (dig->dig_encoder == -1) | 977 | if (dig_encoder == -1) |
977 | return; | 978 | return; |
978 | 979 | ||
979 | if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) | 980 | if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) |
@@ -1023,7 +1024,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t | |||
1023 | 1024 | ||
1024 | if (dig->linkb) | 1025 | if (dig->linkb) |
1025 | args.v3.acConfig.ucLinkSel = 1; | 1026 | args.v3.acConfig.ucLinkSel = 1; |
1026 | if (dig->dig_encoder & 1) | 1027 | if (dig_encoder & 1) |
1027 | args.v3.acConfig.ucEncoderSel = 1; | 1028 | args.v3.acConfig.ucEncoderSel = 1; |
1028 | 1029 | ||
1029 | /* Select the PLL for the PHY | 1030 | /* Select the PLL for the PHY |
@@ -1073,7 +1074,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t | |||
1073 | args.v3.acConfig.fDualLinkConnector = 1; | 1074 | args.v3.acConfig.fDualLinkConnector = 1; |
1074 | } | 1075 | } |
1075 | } else if (ASIC_IS_DCE32(rdev)) { | 1076 | } else if (ASIC_IS_DCE32(rdev)) { |
1076 | args.v2.acConfig.ucEncoderSel = dig->dig_encoder; | 1077 | args.v2.acConfig.ucEncoderSel = dig_encoder; |
1077 | if (dig->linkb) | 1078 | if (dig->linkb) |
1078 | args.v2.acConfig.ucLinkSel = 1; | 1079 | args.v2.acConfig.ucLinkSel = 1; |
1079 | 1080 | ||
@@ -1089,9 +1090,10 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t | |||
1089 | break; | 1090 | break; |
1090 | } | 1091 | } |
1091 | 1092 | ||
1092 | if (is_dp) | 1093 | if (is_dp) { |
1093 | args.v2.acConfig.fCoherentMode = 1; | 1094 | args.v2.acConfig.fCoherentMode = 1; |
1094 | else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { | 1095 | args.v2.acConfig.fDPConnector = 1; |
1096 | } else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { | ||
1095 | if (dig->coherent_mode) | 1097 | if (dig->coherent_mode) |
1096 | args.v2.acConfig.fCoherentMode = 1; | 1098 | args.v2.acConfig.fCoherentMode = 1; |
1097 | if (radeon_encoder->pixel_clock > 165000) | 1099 | if (radeon_encoder->pixel_clock > 165000) |
@@ -1100,7 +1102,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t | |||
1100 | } else { | 1102 | } else { |
1101 | args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL; | 1103 | args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL; |
1102 | 1104 | ||
1103 | if (dig->dig_encoder) | 1105 | if (dig_encoder) |
1104 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER; | 1106 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER; |
1105 | else | 1107 | else |
1106 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER; | 1108 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER; |
@@ -1430,7 +1432,11 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode) | |||
1430 | if (is_dig) { | 1432 | if (is_dig) { |
1431 | switch (mode) { | 1433 | switch (mode) { |
1432 | case DRM_MODE_DPMS_ON: | 1434 | case DRM_MODE_DPMS_ON: |
1433 | atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); | 1435 | /* some early dce3.2 boards have a bug in their transmitter control table */ |
1436 | if ((rdev->family == CHIP_RV710) || (rdev->family == CHIP_RV730)) | ||
1437 | atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); | ||
1438 | else | ||
1439 | atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); | ||
1434 | if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) { | 1440 | if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) { |
1435 | struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); | 1441 | struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); |
1436 | 1442 | ||
@@ -1521,26 +1527,29 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode) | |||
1521 | } | 1527 | } |
1522 | 1528 | ||
1523 | if (ext_encoder) { | 1529 | if (ext_encoder) { |
1524 | int action; | ||
1525 | |||
1526 | switch (mode) { | 1530 | switch (mode) { |
1527 | case DRM_MODE_DPMS_ON: | 1531 | case DRM_MODE_DPMS_ON: |
1528 | default: | 1532 | default: |
1529 | if (ASIC_IS_DCE41(rdev)) | 1533 | if (ASIC_IS_DCE41(rdev)) { |
1530 | action = EXTERNAL_ENCODER_ACTION_V3_ENABLE_OUTPUT; | 1534 | atombios_external_encoder_setup(encoder, ext_encoder, |
1531 | else | 1535 | EXTERNAL_ENCODER_ACTION_V3_ENABLE_OUTPUT); |
1532 | action = ATOM_ENABLE; | 1536 | atombios_external_encoder_setup(encoder, ext_encoder, |
1537 | EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING_OFF); | ||
1538 | } else | ||
1539 | atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE); | ||
1533 | break; | 1540 | break; |
1534 | case DRM_MODE_DPMS_STANDBY: | 1541 | case DRM_MODE_DPMS_STANDBY: |
1535 | case DRM_MODE_DPMS_SUSPEND: | 1542 | case DRM_MODE_DPMS_SUSPEND: |
1536 | case DRM_MODE_DPMS_OFF: | 1543 | case DRM_MODE_DPMS_OFF: |
1537 | if (ASIC_IS_DCE41(rdev)) | 1544 | if (ASIC_IS_DCE41(rdev)) { |
1538 | action = EXTERNAL_ENCODER_ACTION_V3_DISABLE_OUTPUT; | 1545 | atombios_external_encoder_setup(encoder, ext_encoder, |
1539 | else | 1546 | EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING); |
1540 | action = ATOM_DISABLE; | 1547 | atombios_external_encoder_setup(encoder, ext_encoder, |
1548 | EXTERNAL_ENCODER_ACTION_V3_DISABLE_OUTPUT); | ||
1549 | } else | ||
1550 | atombios_external_encoder_setup(encoder, ext_encoder, ATOM_DISABLE); | ||
1541 | break; | 1551 | break; |
1542 | } | 1552 | } |
1543 | atombios_external_encoder_setup(encoder, ext_encoder, action); | ||
1544 | } | 1553 | } |
1545 | 1554 | ||
1546 | radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false); | 1555 | radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false); |
@@ -1999,6 +2008,65 @@ radeon_atom_dac_detect(struct drm_encoder *encoder, struct drm_connector *connec | |||
1999 | return connector_status_disconnected; | 2008 | return connector_status_disconnected; |
2000 | } | 2009 | } |
2001 | 2010 | ||
2011 | static enum drm_connector_status | ||
2012 | radeon_atom_dig_detect(struct drm_encoder *encoder, struct drm_connector *connector) | ||
2013 | { | ||
2014 | struct drm_device *dev = encoder->dev; | ||
2015 | struct radeon_device *rdev = dev->dev_private; | ||
2016 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
2017 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | ||
2018 | struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder); | ||
2019 | u32 bios_0_scratch; | ||
2020 | |||
2021 | if (!ASIC_IS_DCE4(rdev)) | ||
2022 | return connector_status_unknown; | ||
2023 | |||
2024 | if (!ext_encoder) | ||
2025 | return connector_status_unknown; | ||
2026 | |||
2027 | if ((radeon_connector->devices & ATOM_DEVICE_CRT_SUPPORT) == 0) | ||
2028 | return connector_status_unknown; | ||
2029 | |||
2030 | /* load detect on the dp bridge */ | ||
2031 | atombios_external_encoder_setup(encoder, ext_encoder, | ||
2032 | EXTERNAL_ENCODER_ACTION_V3_DACLOAD_DETECTION); | ||
2033 | |||
2034 | bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH); | ||
2035 | |||
2036 | DRM_DEBUG_KMS("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices); | ||
2037 | if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) { | ||
2038 | if (bios_0_scratch & ATOM_S0_CRT1_MASK) | ||
2039 | return connector_status_connected; | ||
2040 | } | ||
2041 | if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) { | ||
2042 | if (bios_0_scratch & ATOM_S0_CRT2_MASK) | ||
2043 | return connector_status_connected; | ||
2044 | } | ||
2045 | if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) { | ||
2046 | if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A)) | ||
2047 | return connector_status_connected; | ||
2048 | } | ||
2049 | if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) { | ||
2050 | if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A)) | ||
2051 | return connector_status_connected; /* CTV */ | ||
2052 | else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A)) | ||
2053 | return connector_status_connected; /* STV */ | ||
2054 | } | ||
2055 | return connector_status_disconnected; | ||
2056 | } | ||
2057 | |||
2058 | void | ||
2059 | radeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder) | ||
2060 | { | ||
2061 | struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder); | ||
2062 | |||
2063 | if (ext_encoder) | ||
2064 | /* ddc_setup on the dp bridge */ | ||
2065 | atombios_external_encoder_setup(encoder, ext_encoder, | ||
2066 | EXTERNAL_ENCODER_ACTION_V3_DDC_SETUP); | ||
2067 | |||
2068 | } | ||
2069 | |||
2002 | static void radeon_atom_encoder_prepare(struct drm_encoder *encoder) | 2070 | static void radeon_atom_encoder_prepare(struct drm_encoder *encoder) |
2003 | { | 2071 | { |
2004 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 2072 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
@@ -2162,7 +2230,7 @@ static const struct drm_encoder_helper_funcs radeon_atom_dig_helper_funcs = { | |||
2162 | .mode_set = radeon_atom_encoder_mode_set, | 2230 | .mode_set = radeon_atom_encoder_mode_set, |
2163 | .commit = radeon_atom_encoder_commit, | 2231 | .commit = radeon_atom_encoder_commit, |
2164 | .disable = radeon_atom_encoder_disable, | 2232 | .disable = radeon_atom_encoder_disable, |
2165 | /* no detect for TMDS/LVDS yet */ | 2233 | .detect = radeon_atom_dig_detect, |
2166 | }; | 2234 | }; |
2167 | 2235 | ||
2168 | static const struct drm_encoder_helper_funcs radeon_atom_dac_helper_funcs = { | 2236 | static const struct drm_encoder_helper_funcs radeon_atom_dac_helper_funcs = { |