drm/i915: Add no-lvds quirk for Supermicro X7SPA-H
[linux-2.6.git] / drivers / gpu / drm / i915 / intel_lvds.c
index 6318828..802fec2 100644 (file)
@@ -187,6 +187,8 @@ centre_horizontally(struct drm_display_mode *mode,
 
        mode->crtc_hsync_start = mode->crtc_hblank_start + sync_pos;
        mode->crtc_hsync_end = mode->crtc_hsync_start + sync_width;
+
+       mode->private_flags |= INTEL_MODE_CRTC_TIMINGS_SET;
 }
 
 static void
@@ -208,6 +210,8 @@ centre_vertically(struct drm_display_mode *mode,
 
        mode->crtc_vsync_start = mode->crtc_vblank_start + sync_pos;
        mode->crtc_vsync_end = mode->crtc_vsync_start + sync_width;
+
+       mode->private_flags |= INTEL_MODE_CRTC_TIMINGS_SET;
 }
 
 static inline u32 panel_fitter_scaling(u32 source, u32 target)
@@ -283,6 +287,8 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
        for_each_pipe(pipe)
                I915_WRITE(BCLRPAT(pipe), 0);
 
+       drm_mode_set_crtcinfo(adjusted_mode, 0);
+
        switch (intel_lvds->fitting_mode) {
        case DRM_MODE_SCALE_CENTER:
                /*
@@ -400,53 +406,21 @@ out:
 
 static void intel_lvds_prepare(struct drm_encoder *encoder)
 {
-       struct drm_device *dev = encoder->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_lvds *intel_lvds = to_intel_lvds(encoder);
 
-       /* We try to do the minimum that is necessary in order to unlock
-        * the registers for mode setting.
-        *
-        * On Ironlake, this is quite simple as we just set the unlock key
-        * and ignore all subtleties. (This may cause some issues...)
-        *
+       /*
         * Prior to Ironlake, we must disable the pipe if we want to adjust
         * the panel fitter. However at all other times we can just reset
         * the registers regardless.
         */
-
-       if (HAS_PCH_SPLIT(dev)) {
-               I915_WRITE(PCH_PP_CONTROL,
-                          I915_READ(PCH_PP_CONTROL) | PANEL_UNLOCK_REGS);
-       } else if (intel_lvds->pfit_dirty) {
-               I915_WRITE(PP_CONTROL,
-                          (I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS)
-                          & ~POWER_TARGET_ON);
-       } else {
-               I915_WRITE(PP_CONTROL,
-                          I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS);
-       }
+       if (!HAS_PCH_SPLIT(encoder->dev) && intel_lvds->pfit_dirty)
+               intel_lvds_disable(intel_lvds);
 }
 
 static void intel_lvds_commit(struct drm_encoder *encoder)
 {
-       struct drm_device *dev = encoder->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_lvds *intel_lvds = to_intel_lvds(encoder);
 
-       /* Undo any unlocking done in prepare to prevent accidental
-        * adjustment of the registers.
-        */
-       if (HAS_PCH_SPLIT(dev)) {
-               u32 val = I915_READ(PCH_PP_CONTROL);
-               if ((val & PANEL_UNLOCK_REGS) == PANEL_UNLOCK_REGS)
-                       I915_WRITE(PCH_PP_CONTROL, val & 0x3);
-       } else {
-               u32 val = I915_READ(PP_CONTROL);
-               if ((val & PANEL_UNLOCK_REGS) == PANEL_UNLOCK_REGS)
-                       I915_WRITE(PP_CONTROL, val & 0x3);
-       }
-
        /* Always do a full power on as we do not know what state
         * we were left in.
         */
@@ -584,6 +558,8 @@ static void intel_lvds_destroy(struct drm_connector *connector)
        struct drm_device *dev = connector->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
 
+       intel_panel_destroy_backlight(dev);
+
        if (dev_priv->lid_notifier.notifier_call)
                acpi_lid_notifier_unregister(&dev_priv->lid_notifier);
        drm_sysfs_connector_remove(connector);
@@ -724,6 +700,14 @@ static const struct dmi_system_id intel_no_lvds[] = {
        },
        {
                .callback = intel_no_lvds_dmi_callback,
+                .ident = "AOpen i45GMx-I",
+                .matches = {
+                        DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
+                        DMI_MATCH(DMI_BOARD_NAME, "i45GMx-I"),
+                },
+        },
+       {
+               .callback = intel_no_lvds_dmi_callback,
                .ident = "Aopen i945GTt-VFA",
                .matches = {
                        DMI_MATCH(DMI_PRODUCT_VERSION, "AO00001JW"),
@@ -738,6 +722,14 @@ static const struct dmi_system_id intel_no_lvds[] = {
                },
        },
        {
+                .callback = intel_no_lvds_dmi_callback,
+                .ident = "Clientron E830",
+                .matches = {
+                        DMI_MATCH(DMI_SYS_VENDOR, "Clientron"),
+                        DMI_MATCH(DMI_PRODUCT_NAME, "E830"),
+                },
+        },
+        {
                .callback = intel_no_lvds_dmi_callback,
                .ident = "Asus EeeBox PC EB1007",
                .matches = {
@@ -745,6 +737,70 @@ static const struct dmi_system_id intel_no_lvds[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "EB1007"),
                },
        },
+       {
+               .callback = intel_no_lvds_dmi_callback,
+               .ident = "Asus AT5NM10T-I",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+                       DMI_MATCH(DMI_BOARD_NAME, "AT5NM10T-I"),
+               },
+       },
+       {
+               .callback = intel_no_lvds_dmi_callback,
+               .ident = "Hewlett-Packard HP t5740e Thin Client",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP t5740e Thin Client"),
+               },
+       },
+       {
+               .callback = intel_no_lvds_dmi_callback,
+               .ident = "Hewlett-Packard t5745",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "hp t5745"),
+               },
+       },
+       {
+               .callback = intel_no_lvds_dmi_callback,
+               .ident = "Hewlett-Packard st5747",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "hp st5747"),
+               },
+       },
+       {
+               .callback = intel_no_lvds_dmi_callback,
+               .ident = "MSI Wind Box DC500",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"),
+                       DMI_MATCH(DMI_BOARD_NAME, "MS-7469"),
+               },
+       },
+       {
+               .callback = intel_no_lvds_dmi_callback,
+               .ident = "ZOTAC ZBOXSD-ID12/ID13",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "ZOTAC"),
+                       DMI_MATCH(DMI_BOARD_NAME, "ZBOXSD-ID12/ID13"),
+               },
+       },
+       {
+               .callback = intel_no_lvds_dmi_callback,
+               .ident = "Gigabyte GA-D525TUD",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co., Ltd."),
+                       DMI_MATCH(DMI_BOARD_NAME, "D525TUD"),
+               },
+       },
+       {
+               .callback = intel_no_lvds_dmi_callback,
+               .ident = "Supermicro X7SPA-H",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Supermicro"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "X7SPA-H"),
+               },
+       },
 
        { }     /* terminating entry */
 };
@@ -850,6 +906,18 @@ static bool lvds_is_present_in_vbt(struct drm_device *dev,
        return false;
 }
 
+static bool intel_lvds_supported(struct drm_device *dev)
+{
+       /* With the introduction of the PCH we gained a dedicated
+        * LVDS presence pin, use it. */
+       if (HAS_PCH_SPLIT(dev))
+               return true;
+
+       /* Otherwise LVDS was only attached to mobile products,
+        * except for the inglorious 830gm */
+       return IS_MOBILE(dev) && !IS_I830(dev);
+}
+
 /**
  * intel_lvds_init - setup LVDS connectors on this device
  * @dev: drm device
@@ -871,6 +939,9 @@ bool intel_lvds_init(struct drm_device *dev)
        int pipe;
        u8 pin;
 
+       if (!intel_lvds_supported(dev))
+               return false;
+
        /* Skip init on machines we know falsely report LVDS */
        if (dmi_check_system(intel_no_lvds))
                return false;
@@ -918,9 +989,11 @@ bool intel_lvds_init(struct drm_device *dev)
        intel_encoder->type = INTEL_OUTPUT_LVDS;
 
        intel_encoder->clone_mask = (1 << INTEL_LVDS_CLONE_BIT);
-       intel_encoder->crtc_mask = (1 << 1);
-       if (INTEL_INFO(dev)->gen >= 5)
-               intel_encoder->crtc_mask |= (1 << 0);
+       if (HAS_PCH_SPLIT(dev))
+               intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
+       else
+               intel_encoder->crtc_mask = (1 << 1);
+
        drm_encoder_helper_add(encoder, &intel_lvds_helper_funcs);
        drm_connector_helper_add(connector, &intel_lvds_connector_helper_funcs);
        connector->display_info.subpixel_order = SubPixelHorizontalRGB;
@@ -1042,6 +1115,19 @@ out:
                pwm = I915_READ(BLC_PWM_PCH_CTL1);
                pwm |= PWM_PCH_ENABLE;
                I915_WRITE(BLC_PWM_PCH_CTL1, pwm);
+               /*
+                * Unlock registers and just
+                * leave them unlocked
+                */
+               I915_WRITE(PCH_PP_CONTROL,
+                          I915_READ(PCH_PP_CONTROL) | PANEL_UNLOCK_REGS);
+       } else {
+               /*
+                * Unlock registers and just
+                * leave them unlocked
+                */
+               I915_WRITE(PP_CONTROL,
+                          I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS);
        }
        dev_priv->lid_notifier.notifier_call = intel_lid_notify;
        if (acpi_lid_notifier_register(&dev_priv->lid_notifier)) {
@@ -1051,6 +1137,9 @@ out:
        /* keep the LVDS connector */
        dev_priv->int_lvds_connector = connector;
        drm_sysfs_connector_add(connector);
+
+       intel_panel_setup_backlight(dev);
+
        return true;
 
 failed: