aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorAlex Deucher <alexdeucher@gmail.com>2010-11-16 12:09:42 -0500
committerDave Airlie <airlied@redhat.com>2010-11-17 23:56:36 -0500
commit3e4b99828d1c8abefefd37474503605c811c1b51 (patch)
tree5792ec99ba96007a7f041ff966bea13c08ec8d8a /drivers/gpu
parent99999aaa091bdb3e16b5eed22f3a9a567f84f0fe (diff)
drm/radeon/kms/atom: add proper external encoders support
These are external encoder chips connected via DVO or DP. The actual external encoder programming is handled by the kms encoder functions for primary encoder. Signed-off-by: Alex Deucher <alexdeucher@gmail.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/radeon/radeon_encoders.c183
-rw-r--r--drivers/gpu/drm/radeon/radeon_mode.h1
2 files changed, 184 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c
index 07df990a897b..041943df966b 100644
--- a/drivers/gpu/drm/radeon/radeon_encoders.c
+++ b/drivers/gpu/drm/radeon/radeon_encoders.c
@@ -229,6 +229,27 @@ radeon_get_connector_for_encoder(struct drm_encoder *encoder)
229 return NULL; 229 return NULL;
230} 230}
231 231
232struct 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
232void radeon_panel_mode_fixup(struct drm_encoder *encoder, 253void radeon_panel_mode_fixup(struct drm_encoder *encoder,
233 struct drm_display_mode *adjusted_mode) 254 struct drm_display_mode *adjusted_mode)
234{ 255{
@@ -1021,6 +1042,75 @@ atombios_set_edp_panel_power(struct drm_connector *connector, int action)
1021 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 1042 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1022} 1043}
1023 1044
1045union external_encoder_control {
1046 EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION v1;
1047};
1048
1049static void
1050atombios_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
1024static void 1114static void
1025atombios_yuv_setup(struct drm_encoder *encoder, bool enable) 1115atombios_yuv_setup(struct drm_encoder *encoder, bool enable)
1026{ 1116{
@@ -1064,6 +1154,7 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
1064 struct drm_device *dev = encoder->dev; 1154 struct drm_device *dev = encoder->dev;
1065 struct radeon_device *rdev = dev->dev_private; 1155 struct radeon_device *rdev = dev->dev_private;
1066 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);
1067 DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args; 1158 DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args;
1068 int index = 0; 1159 int index = 0;
1069 bool is_dig = false; 1160 bool is_dig = false;
@@ -1191,6 +1282,24 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
1191 break; 1282 break;
1192 } 1283 }
1193 } 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
1194 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);
1195 1304
1196} 1305}
@@ -1438,6 +1547,7 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
1438 struct drm_device *dev = encoder->dev; 1547 struct drm_device *dev = encoder->dev;
1439 struct radeon_device *rdev = dev->dev_private; 1548 struct radeon_device *rdev = dev->dev_private;
1440 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);
1441 1551
1442 radeon_encoder->pixel_clock = adjusted_mode->clock; 1552 radeon_encoder->pixel_clock = adjusted_mode->clock;
1443 1553
@@ -1498,6 +1608,11 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
1498 } 1608 }
1499 break; 1609 break;
1500 } 1610 }
1611
1612 if (ext_encoder) {
1613 atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
1614 }
1615
1501 atombios_apply_encoder_quirks(encoder, adjusted_mode); 1616 atombios_apply_encoder_quirks(encoder, adjusted_mode);
1502 1617
1503 if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) { 1618 if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) {
@@ -1698,6 +1813,53 @@ disable_done:
1698 radeon_encoder->active_device = 0; 1813 radeon_encoder->active_device = 0;
1699} 1814}
1700 1815
1816/* these are handled by the primary encoders */
1817static void radeon_atom_ext_prepare(struct drm_encoder *encoder)
1818{
1819
1820}
1821
1822static void radeon_atom_ext_commit(struct drm_encoder *encoder)
1823{
1824
1825}
1826
1827static void
1828radeon_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
1835static void radeon_atom_ext_disable(struct drm_encoder *encoder)
1836{
1837
1838}
1839
1840static void
1841radeon_atom_ext_dpms(struct drm_encoder *encoder, int mode)
1842{
1843
1844}
1845
1846static 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
1853static 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
1701static const struct drm_encoder_helper_funcs radeon_atom_dig_helper_funcs = { 1863static const struct drm_encoder_helper_funcs radeon_atom_dig_helper_funcs = {
1702 .dpms = radeon_atom_encoder_dpms, 1864 .dpms = radeon_atom_encoder_dpms,
1703 .mode_fixup = radeon_atom_mode_fixup, 1865 .mode_fixup = radeon_atom_mode_fixup,
@@ -1807,6 +1969,7 @@ radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_enum, uint32_t
1807 radeon_encoder->devices = supported_device; 1969 radeon_encoder->devices = supported_device;
1808 radeon_encoder->rmx_type = RMX_OFF; 1970 radeon_encoder->rmx_type = RMX_OFF;
1809 radeon_encoder->underscan_type = UNDERSCAN_OFF; 1971 radeon_encoder->underscan_type = UNDERSCAN_OFF;
1972 radeon_encoder->is_ext_encoder = false;
1810 1973
1811 switch (radeon_encoder->encoder_id) { 1974 switch (radeon_encoder->encoder_id) {
1812 case ENCODER_OBJECT_ID_INTERNAL_LVDS: 1975 case ENCODER_OBJECT_ID_INTERNAL_LVDS:
@@ -1848,6 +2011,9 @@ radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_enum, uint32_t
1848 radeon_encoder->rmx_type = RMX_FULL; 2011 radeon_encoder->rmx_type = RMX_FULL;
1849 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);
1850 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);
1851 } else { 2017 } else {
1852 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);
1853 radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder); 2019 radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
@@ -1856,5 +2022,22 @@ radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_enum, uint32_t
1856 } 2022 }
1857 drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs); 2023 drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs);
1858 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;
1859 } 2042 }
1860} 2043}
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index 663bc51cf99e..e301c6f9e059 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -375,6 +375,7 @@ struct radeon_encoder {
375 int hdmi_config_offset; 375 int hdmi_config_offset;
376 int hdmi_audio_workaround; 376 int hdmi_audio_workaround;
377 int hdmi_buffer_status; 377 int hdmi_buffer_status;
378 bool is_ext_encoder;
378}; 379};
379 380
380struct radeon_connector_atom_dig { 381struct radeon_connector_atom_dig {