aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Deucher <alexdeucher@gmail.com>2010-11-22 17:56:24 -0500
committerDave Airlie <airlied@redhat.com>2010-11-22 18:23:21 -0500
commitbf982ebf22d5d84dd4a2a8d8f1a11f75920020a7 (patch)
treeb5337e80d1ef5b9f0cc8f372b923bc4d510a975b
parent4e8c65a1f9ee1a976d95c1d5d2027761aba2f1c3 (diff)
drm/radeon/kms: Add support for external encoders on fusion APUs
Signed-off-by: Alex Deucher <alexdeucher@gmail.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--drivers/gpu/drm/radeon/radeon_display.c4
-rw-r--r--drivers/gpu/drm/radeon/radeon_encoders.c54
2 files changed, 54 insertions, 4 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 1df4dc6c063c..2697801e36e7 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -225,7 +225,7 @@ static void radeon_crtc_init(struct drm_device *dev, int index)
225 radeon_legacy_init_crtc(dev, radeon_crtc); 225 radeon_legacy_init_crtc(dev, radeon_crtc);
226} 226}
227 227
228static const char *encoder_names[34] = { 228static const char *encoder_names[36] = {
229 "NONE", 229 "NONE",
230 "INTERNAL_LVDS", 230 "INTERNAL_LVDS",
231 "INTERNAL_TMDS1", 231 "INTERNAL_TMDS1",
@@ -260,6 +260,8 @@ static const char *encoder_names[34] = {
260 "INTERNAL_KLDSCP_LVTMA", 260 "INTERNAL_KLDSCP_LVTMA",
261 "INTERNAL_UNIPHY1", 261 "INTERNAL_UNIPHY1",
262 "INTERNAL_UNIPHY2", 262 "INTERNAL_UNIPHY2",
263 "NUTMEG",
264 "TRAVIS",
263}; 265};
264 266
265static const char *connector_names[15] = { 267static const char *connector_names[15] = {
diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c
index 806d552299bf..e4e64a80b58d 100644
--- a/drivers/gpu/drm/radeon/radeon_encoders.c
+++ b/drivers/gpu/drm/radeon/radeon_encoders.c
@@ -1056,6 +1056,7 @@ atombios_set_edp_panel_power(struct drm_connector *connector, int action)
1056 1056
1057union external_encoder_control { 1057union external_encoder_control {
1058 EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION v1; 1058 EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION v1;
1059 EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3 v3;
1059}; 1060};
1060 1061
1061static void 1062static void
@@ -1066,6 +1067,7 @@ atombios_external_encoder_setup(struct drm_encoder *encoder,
1066 struct drm_device *dev = encoder->dev; 1067 struct drm_device *dev = encoder->dev;
1067 struct radeon_device *rdev = dev->dev_private; 1068 struct radeon_device *rdev = dev->dev_private;
1068 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 1069 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1070 struct radeon_encoder *ext_radeon_encoder = to_radeon_encoder(ext_encoder);
1069 union external_encoder_control args; 1071 union external_encoder_control args;
1070 struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); 1072 struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
1071 int index = GetIndexIntoMasterTable(COMMAND, ExternalEncoderControl); 1073 int index = GetIndexIntoMasterTable(COMMAND, ExternalEncoderControl);
@@ -1073,6 +1075,7 @@ atombios_external_encoder_setup(struct drm_encoder *encoder,
1073 int dp_clock = 0; 1075 int dp_clock = 0;
1074 int dp_lane_count = 0; 1076 int dp_lane_count = 0;
1075 int connector_object_id = 0; 1077 int connector_object_id = 0;
1078 u32 ext_enum = (ext_radeon_encoder->encoder_enum & ENUM_ID_MASK) >> ENUM_ID_SHIFT;
1076 1079
1077 if (connector) { 1080 if (connector) {
1078 struct radeon_connector *radeon_connector = to_radeon_connector(connector); 1081 struct radeon_connector *radeon_connector = to_radeon_connector(connector);
@@ -1111,6 +1114,37 @@ atombios_external_encoder_setup(struct drm_encoder *encoder,
1111 else 1114 else
1112 args.v1.sDigEncoder.ucLaneNum = 4; 1115 args.v1.sDigEncoder.ucLaneNum = 4;
1113 break; 1116 break;
1117 case 3:
1118 args.v3.sExtEncoder.ucAction = action;
1119 if (action == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT)
1120 args.v3.sExtEncoder.usConnectorId = connector_object_id;
1121 else
1122 args.v3.sExtEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
1123 args.v3.sExtEncoder.ucEncoderMode = atombios_get_encoder_mode(encoder);
1124
1125 if (args.v3.sExtEncoder.ucEncoderMode == ATOM_ENCODER_MODE_DP) {
1126 if (dp_clock == 270000)
1127 args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ;
1128 else if (dp_clock == 540000)
1129 args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_5_40GHZ;
1130 args.v3.sExtEncoder.ucLaneNum = dp_lane_count;
1131 } else if (radeon_encoder->pixel_clock > 165000)
1132 args.v3.sExtEncoder.ucLaneNum = 8;
1133 else
1134 args.v3.sExtEncoder.ucLaneNum = 4;
1135 switch (ext_enum) {
1136 case GRAPH_OBJECT_ENUM_ID1:
1137 args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER1;
1138 break;
1139 case GRAPH_OBJECT_ENUM_ID2:
1140 args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER2;
1141 break;
1142 case GRAPH_OBJECT_ENUM_ID3:
1143 args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER3;
1144 break;
1145 }
1146 args.v3.sExtEncoder.ucBitPerColor = PANEL_8BIT_PER_COLOR;
1147 break;
1114 default: 1148 default:
1115 DRM_ERROR("Unknown table version: %d, %d\n", frev, crev); 1149 DRM_ERROR("Unknown table version: %d, %d\n", frev, crev);
1116 return; 1150 return;
@@ -1301,12 +1335,18 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
1301 switch (mode) { 1335 switch (mode) {
1302 case DRM_MODE_DPMS_ON: 1336 case DRM_MODE_DPMS_ON:
1303 default: 1337 default:
1304 action = ATOM_ENABLE; 1338 if (ASIC_IS_DCE41(rdev) && (rdev->flags & RADEON_IS_IGP))
1339 action = EXTERNAL_ENCODER_ACTION_V3_ENABLE_OUTPUT;
1340 else
1341 action = ATOM_ENABLE;
1305 break; 1342 break;
1306 case DRM_MODE_DPMS_STANDBY: 1343 case DRM_MODE_DPMS_STANDBY:
1307 case DRM_MODE_DPMS_SUSPEND: 1344 case DRM_MODE_DPMS_SUSPEND:
1308 case DRM_MODE_DPMS_OFF: 1345 case DRM_MODE_DPMS_OFF:
1309 action = ATOM_DISABLE; 1346 if (ASIC_IS_DCE41(rdev) && (rdev->flags & RADEON_IS_IGP))
1347 action = EXTERNAL_ENCODER_ACTION_V3_DISABLE_OUTPUT;
1348 else
1349 action = ATOM_DISABLE;
1310 break; 1350 break;
1311 } 1351 }
1312 atombios_external_encoder_setup(encoder, ext_encoder, action); 1352 atombios_external_encoder_setup(encoder, ext_encoder, action);
@@ -1627,7 +1667,13 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
1627 } 1667 }
1628 1668
1629 if (ext_encoder) { 1669 if (ext_encoder) {
1630 atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE); 1670 if (ASIC_IS_DCE41(rdev) && (rdev->flags & RADEON_IS_IGP)) {
1671 atombios_external_encoder_setup(encoder, ext_encoder,
1672 EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT);
1673 atombios_external_encoder_setup(encoder, ext_encoder,
1674 EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP);
1675 } else
1676 atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
1631 } 1677 }
1632 1678
1633 atombios_apply_encoder_quirks(encoder, adjusted_mode); 1679 atombios_apply_encoder_quirks(encoder, adjusted_mode);
@@ -2046,6 +2092,8 @@ radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_enum, uint32_t
2046 case ENCODER_OBJECT_ID_TITFP513: 2092 case ENCODER_OBJECT_ID_TITFP513:
2047 case ENCODER_OBJECT_ID_VT1623: 2093 case ENCODER_OBJECT_ID_VT1623:
2048 case ENCODER_OBJECT_ID_HDMI_SI1930: 2094 case ENCODER_OBJECT_ID_HDMI_SI1930:
2095 case ENCODER_OBJECT_ID_TRAVIS:
2096 case ENCODER_OBJECT_ID_NUTMEG:
2049 /* these are handled by the primary encoders */ 2097 /* these are handled by the primary encoders */
2050 radeon_encoder->is_ext_encoder = true; 2098 radeon_encoder->is_ext_encoder = true;
2051 if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) 2099 if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))