]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/gpu/drm/i915/intel_display.c
drm/i915: Allow LVDS on pipe A on gen4+
[karo-tx-linux.git] / drivers / gpu / drm / i915 / intel_display.c
index 34d2652f405f6549c88dbd1cafefb21bf1c86c77..eb4a265861ec0bb8f9c6e816eb1d44380c3228af 100644 (file)
@@ -741,12 +741,11 @@ bool intel_pipe_has_type (struct drm_crtc *crtc, int type)
 {
     struct drm_device *dev = crtc->dev;
     struct drm_mode_config *mode_config = &dev->mode_config;
-    struct drm_connector *l_entry;
+    struct drm_encoder *l_entry;
 
-    list_for_each_entry(l_entry, &mode_config->connector_list, head) {
-           if (l_entry->encoder &&
-               l_entry->encoder->crtc == crtc) {
-                   struct intel_encoder *intel_encoder = to_intel_encoder(l_entry);
+    list_for_each_entry(l_entry, &mode_config->encoder_list, head) {
+           if (l_entry && l_entry->crtc == crtc) {
+                   struct intel_encoder *intel_encoder = enc_to_intel_encoder(l_entry);
                    if (intel_encoder->type == type)
                            return true;
            }
@@ -2923,7 +2922,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
        bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false;
        bool is_edp = false;
        struct drm_mode_config *mode_config = &dev->mode_config;
-       struct drm_connector *connector;
+       struct drm_encoder *encoder;
+       struct intel_encoder *intel_encoder;
        const intel_limit_t *limit;
        int ret;
        struct fdi_m_n m_n = {0};
@@ -2941,12 +2941,13 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
 
        drm_vblank_pre_modeset(dev, pipe);
 
-       list_for_each_entry(connector, &mode_config->connector_list, head) {
-               struct intel_encoder *intel_encoder = to_intel_encoder(connector);
+       list_for_each_entry(encoder, &mode_config->encoder_list, head) {
 
-               if (!connector->encoder || connector->encoder->crtc != crtc)
+               if (!encoder || encoder->crtc != crtc)
                        continue;
 
+               intel_encoder = enc_to_intel_encoder(encoder);
+
                switch (intel_encoder->type) {
                case INTEL_OUTPUT_LVDS:
                        is_lvds = true;
@@ -3302,7 +3303,9 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
                        lvds_reg = PCH_LVDS;
 
                lvds = I915_READ(lvds_reg);
-               lvds |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP | LVDS_PIPEB_SELECT;
+               lvds |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
+               if (pipe == 1)
+                       lvds |= LVDS_PIPEB_SELECT;
                /* set the corresponsding LVDS_BORDER bit */
                lvds |= dev_priv->lvds_border_bits;
                /* Set the B0-B3 data pairs corresponding to whether we're going to
@@ -3670,6 +3673,7 @@ static struct drm_display_mode load_detect_mode = {
 };
 
 struct drm_crtc *intel_get_load_detect_pipe(struct intel_encoder *intel_encoder,
+                                           struct drm_connector *connector,
                                            struct drm_display_mode *mode,
                                            int *dpms_mode)
 {
@@ -3728,7 +3732,7 @@ struct drm_crtc *intel_get_load_detect_pipe(struct intel_encoder *intel_encoder,
        }
 
        encoder->crtc = crtc;
-       intel_encoder->base.encoder = encoder;
+       connector->encoder = encoder;
        intel_encoder->load_detect_temp = true;
 
        intel_crtc = to_intel_crtc(crtc);
@@ -3754,7 +3758,8 @@ struct drm_crtc *intel_get_load_detect_pipe(struct intel_encoder *intel_encoder,
        return crtc;
 }
 
-void intel_release_load_detect_pipe(struct intel_encoder *intel_encoder, int dpms_mode)
+void intel_release_load_detect_pipe(struct intel_encoder *intel_encoder,
+                                   struct drm_connector *connector, int dpms_mode)
 {
        struct drm_encoder *encoder = &intel_encoder->enc;
        struct drm_device *dev = encoder->dev;
@@ -3764,7 +3769,7 @@ void intel_release_load_detect_pipe(struct intel_encoder *intel_encoder, int dpm
 
        if (intel_encoder->load_detect_temp) {
                encoder->crtc = NULL;
-               intel_encoder->base.encoder = NULL;
+               connector->encoder = NULL;
                intel_encoder->load_detect_temp = false;
                crtc->enabled = drm_helper_crtc_in_use(crtc);
                drm_helper_disable_unused_functions(dev);
@@ -4391,14 +4396,14 @@ struct drm_crtc *intel_get_crtc_from_pipe(struct drm_device *dev, int pipe)
        return crtc;
 }
 
-static int intel_connector_clones(struct drm_device *dev, int type_mask)
+static int intel_encoder_clones(struct drm_device *dev, int type_mask)
 {
        int index_mask = 0;
-       struct drm_connector *connector;
+       struct drm_encoder *encoder;
        int entry = 0;
 
-        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-               struct intel_encoder *intel_encoder = to_intel_encoder(connector);
+        list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+               struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
                if (type_mask & intel_encoder->clone_mask)
                        index_mask |= (1 << entry);
                entry++;
@@ -4410,7 +4415,7 @@ static int intel_connector_clones(struct drm_device *dev, int type_mask)
 static void intel_setup_outputs(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct drm_connector *connector;
+       struct drm_encoder *encoder;
 
        intel_crt_init(dev);
 
@@ -4493,12 +4498,11 @@ static void intel_setup_outputs(struct drm_device *dev)
        if (SUPPORTS_TV(dev))
                intel_tv_init(dev);
 
-       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-               struct intel_encoder *intel_encoder = to_intel_encoder(connector);
-               struct drm_encoder *encoder = &intel_encoder->enc;
+       list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+               struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
 
                encoder->possible_crtcs = intel_encoder->crtc_mask;
-               encoder->possible_clones = intel_connector_clones(dev,
+               encoder->possible_clones = intel_encoder_clones(dev,
                                                intel_encoder->clone_mask);
        }
 }
@@ -4982,6 +4986,31 @@ struct drm_encoder *intel_best_encoder(struct drm_connector *connector)
        return &intel_encoder->enc;
 }
 
+/*
+ * Return which encoder is currently attached for connector.
+ */
+struct drm_encoder *intel_attached_encoder (struct drm_connector *connector)
+{
+       struct drm_mode_object *obj;
+       struct drm_encoder *encoder;
+       int i;
+
+       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);
+               return encoder;
+       }
+       return NULL;
+}
+
 /*
  * set vga decode state - true == enable VGA decode
  */