drm/i915: track is_dual_link in intel_lvds
authorDaniel Vetter <daniel.vetter@ffwll.ch>
Mon, 26 Nov 2012 16:22:10 +0000 (17:22 +0100)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Thu, 29 Nov 2012 11:36:57 +0000 (12:36 +0100)
Yeah, all users (both the clock selection special cases and the lvds
pin pair stuff) are still in common code, but this will change.

v2: Rebase on top of Jani Nikula's panel rework.

v3: Incorporate review from Paulo Zanoni:
- s/__is_dual_link_lvds/compute_is_dual_link_lvds
- kill dev_priv->lvds_val
- drop spurious whitespace change

v4: Add a debug printk to display the dual-link status, as suggested
by Paulo Zanoni in review.

Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com> (v3)
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/intel_lvds.c

index 79589bb..9be7efd 100644 (file)
@@ -705,7 +705,6 @@ typedef struct drm_i915_private {
        unsigned int display_clock_mode:1;
        int lvds_ssc_freq;
        unsigned int bios_lvds_val; /* initial [PCH_]LVDS reg val in VBIOS */
-       unsigned int lvds_val; /* used for checking LVDS channel mode */
        struct {
                int rate;
                int lanes;
index 4158a88..31fdbfd 100644 (file)
@@ -52,6 +52,7 @@ struct intel_lvds_encoder {
        u32 pfit_control;
        u32 pfit_pgm_ratios;
        bool pfit_dirty;
+       bool is_dual_link;
 
        struct intel_lvds_connector *attached_connector;
 };
@@ -923,6 +924,23 @@ static const struct dmi_system_id intel_dual_link_lvds[] = {
 
 bool intel_is_dual_link_lvds(struct drm_device *dev)
 {
+       struct intel_encoder *encoder;
+       struct intel_lvds_encoder *lvds_encoder;
+
+       list_for_each_entry(encoder, &dev->mode_config.encoder_list,
+                           base.head) {
+               if (encoder->type == INTEL_OUTPUT_LVDS) {
+                       lvds_encoder = to_lvds_encoder(&encoder->base);
+
+                       return lvds_encoder->is_dual_link;
+               }
+       }
+
+       return false;
+}
+
+static bool compute_is_dual_link_lvds(struct drm_device *dev)
+{
        unsigned int val;
        struct drm_i915_private *dev_priv = dev->dev_private;
        u32 lvds_reg;
@@ -940,19 +958,15 @@ bool intel_is_dual_link_lvds(struct drm_device *dev)
        if (dmi_check_system(intel_dual_link_lvds))
                return true;
 
-       if (dev_priv->lvds_val)
-               val = dev_priv->lvds_val;
-       else {
-               /* BIOS should set the proper LVDS register value at boot, but
-                * in reality, it doesn't set the value when the lid is closed;
-                * we need to check "the value to be set" in VBT when LVDS
-                * register is uninitialized.
-                */
-               val = I915_READ(lvds_reg);
-               if (!(val & ~(LVDS_PIPE_MASK | LVDS_DETECTED)))
-                       val = dev_priv->bios_lvds_val;
-               dev_priv->lvds_val = val;
-       }
+       /* BIOS should set the proper LVDS register value at boot, but
+        * in reality, it doesn't set the value when the lid is closed;
+        * we need to check "the value to be set" in VBT when LVDS
+        * register is uninitialized.
+        */
+       val = I915_READ(lvds_reg);
+       if (!(val & ~(LVDS_PIPE_MASK | LVDS_DETECTED)))
+               val = dev_priv->bios_lvds_val;
+
        return (val & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP;
 }
 
@@ -1162,6 +1176,10 @@ bool intel_lvds_init(struct drm_device *dev)
                goto failed;
 
 out:
+       lvds_encoder->is_dual_link = compute_is_dual_link_lvds(dev);
+       DRM_DEBUG_KMS("detected %s-link lvds configuration\n",
+                     lvds_encoder->is_dual_link ? "dual" : "single");
+
        /*
         * Unlock registers and just
         * leave them unlocked