diff options
| author | Alex Deucher <alexdeucher@gmail.com> | 2010-11-22 17:56:24 -0500 |
|---|---|---|
| committer | Dave Airlie <airlied@redhat.com> | 2010-11-22 18:23:21 -0500 |
| commit | bf982ebf22d5d84dd4a2a8d8f1a11f75920020a7 (patch) | |
| tree | b5337e80d1ef5b9f0cc8f372b923bc4d510a975b | |
| parent | 4e8c65a1f9ee1a976d95c1d5d2027761aba2f1c3 (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.c | 4 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_encoders.c | 54 |
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 | ||
| 228 | static const char *encoder_names[34] = { | 228 | static 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 | ||
| 265 | static const char *connector_names[15] = { | 267 | static 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 | ||
| 1057 | union external_encoder_control { | 1057 | union 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 | ||
| 1061 | static void | 1062 | static 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)) |
