drm/radeon/kms: add some dp encoder/connector helper funcs
authorAlex Deucher <alexdeucher@gmail.com>
Fri, 20 May 2011 08:34:21 +0000 (04:34 -0400)
committerDave Airlie <airlied@redhat.com>
Fri, 20 May 2011 10:02:26 +0000 (20:02 +1000)
Used for dp1.2 support and for dp bridges.

Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
drivers/gpu/drm/radeon/radeon_connectors.c
drivers/gpu/drm/radeon/radeon_encoders.c
drivers/gpu/drm/radeon/radeon_mode.h

index a7bdcc7553ad9570ae1040220569c8e8c9fc1815..9f3c6509d9d035a5306c80cdabda31da035cd828 100644 (file)
@@ -1068,6 +1068,77 @@ static int radeon_dp_get_modes(struct drm_connector *connector)
        return ret;
 }
 
+bool radeon_connector_encoder_is_dp_bridge(struct drm_connector *connector)
+{
+       struct drm_mode_object *obj;
+       struct drm_encoder *encoder;
+       struct radeon_encoder *radeon_encoder;
+       int i;
+       bool found = false;
+
+       for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
+               if (connector->encoder_ids[i] == 0)
+                       break;
+
+               obj = drm_mode_object_find(connector->dev, connector->encoder_ids[i], DRM_MODE_OBJECT_ENCODER);
+               if (!obj)
+                       continue;
+
+               encoder = obj_to_encoder(obj);
+               radeon_encoder = to_radeon_encoder(encoder);
+
+               switch (radeon_encoder->encoder_id) {
+               case ENCODER_OBJECT_ID_TRAVIS:
+               case ENCODER_OBJECT_ID_NUTMEG:
+                       found = true;
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       return found;
+}
+
+bool radeon_connector_encoder_is_hbr2(struct drm_connector *connector)
+{
+       struct drm_mode_object *obj;
+       struct drm_encoder *encoder;
+       struct radeon_encoder *radeon_encoder;
+       int i;
+       bool found = false;
+
+       for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
+               if (connector->encoder_ids[i] == 0)
+                       break;
+
+               obj = drm_mode_object_find(connector->dev, connector->encoder_ids[i], DRM_MODE_OBJECT_ENCODER);
+               if (!obj)
+                       continue;
+
+               encoder = obj_to_encoder(obj);
+               radeon_encoder = to_radeon_encoder(encoder);
+               if (radeon_encoder->caps & ATOM_ENCODER_CAP_RECORD_HBR2)
+                       found = true;
+       }
+
+       return found;
+}
+
+bool radeon_connector_is_dp12_capable(struct drm_connector *connector)
+{
+       struct drm_device *dev = connector->dev;
+       struct radeon_device *rdev = dev->dev_private;
+
+       if (ASIC_IS_DCE5(rdev) &&
+           (rdev->clock.dp_extclk >= 53900) &&
+           radeon_connector_encoder_is_hbr2(connector)) {
+               return true;
+       }
+
+       return false;
+}
+
 static enum drm_connector_status
 radeon_dp_detect(struct drm_connector *connector, bool force)
 {
index fd0087faf758686996e5d7eae7659a1f62a36400..1c064e78f21aa4a465f8ca4a72503b991dcb517d 100644 (file)
@@ -250,6 +250,25 @@ struct drm_encoder *radeon_atom_get_external_encoder(struct drm_encoder *encoder
        return NULL;
 }
 
+bool radeon_encoder_is_dp_bridge(struct drm_encoder *encoder)
+{
+       struct drm_encoder *other_encoder = radeon_atom_get_external_encoder(encoder);
+
+       if (other_encoder) {
+               struct radeon_encoder *radeon_encoder = to_radeon_encoder(other_encoder);
+
+               switch (radeon_encoder->encoder_id) {
+               case ENCODER_OBJECT_ID_TRAVIS:
+               case ENCODER_OBJECT_ID_NUTMEG:
+                       return true;
+               default:
+                       return false;
+               }
+       }
+
+       return false;
+}
+
 void radeon_panel_mode_fixup(struct drm_encoder *encoder,
                             struct drm_display_mode *adjusted_mode)
 {
@@ -621,6 +640,10 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
        struct radeon_connector *radeon_connector;
        struct radeon_connector_atom_dig *dig_connector;
 
+       /* dp bridges are always DP */
+       if (radeon_encoder_is_dp_bridge(encoder))
+               return ATOM_ENCODER_MODE_DP;
+
        connector = radeon_get_connector_for_encoder(encoder);
        if (!connector) {
                switch (radeon_encoder->encoder_id) {
index e4d32373c6304e1e07fc9173ade2870eb12dc52c..7a3cfa09d45fd030b26c34d5258fb1be4e8a07fb 100644 (file)
@@ -464,6 +464,11 @@ radeon_atombios_get_tv_info(struct radeon_device *rdev);
 extern struct drm_connector *
 radeon_get_connector_for_encoder(struct drm_encoder *encoder);
 
+extern bool radeon_encoder_is_dp_bridge(struct drm_encoder *encoder);
+extern bool radeon_connector_encoder_is_dp_bridge(struct drm_connector *connector);
+extern bool radeon_connector_encoder_is_hbr2(struct drm_connector *connector);
+extern bool radeon_connector_is_dp12_capable(struct drm_connector *connector);
+
 extern void radeon_connector_hotplug(struct drm_connector *connector);
 extern bool radeon_dp_needs_link_train(struct radeon_connector *radeon_connector);
 extern int radeon_dp_mode_valid_helper(struct radeon_connector *radeon_connector,