diff mbox

[05/10] drm/i915: Move the ACPI lid notifier away from LVDS to the generic panel

Message ID 1303463958-17128-6-git-send-email-chris@chris-wilson.co.uk (mailing list archive)
State New, archived
Headers show

Commit Message

Chris Wilson April 22, 2011, 9:19 a.m. UTC
... in preparation for enabling it from eDP as well.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/intel_drv.h   |    8 +++
 drivers/gpu/drm/i915/intel_lvds.c  |   79 ++-----------------------------
 drivers/gpu/drm/i915/intel_panel.c |   92 ++++++++++++++++++++++++++++++++++++
 3 files changed, 104 insertions(+), 75 deletions(-)

Comments

Jesse Barnes April 22, 2011, 4:21 p.m. UTC | #1
On Fri, 22 Apr 2011 10:19:13 +0100
Chris Wilson <chris@chris-wilson.co.uk> wrote:

> ... in preparation for enabling it from eDP as well.
> 
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> ---
>  drivers/gpu/drm/i915/intel_drv.h   |    8 +++
>  drivers/gpu/drm/i915/intel_lvds.c  |   79 ++-----------------------------
>  drivers/gpu/drm/i915/intel_panel.c |   92 ++++++++++++++++++++++++++++++++++++
>  3 files changed, 104 insertions(+), 75 deletions(-)

Not sure if this one or 6/10 are needed.  Originally we added lid
status support to detect LVDS presence and to reset modes if the BIOS
shut off planes/pipes at lid close time.

But neither of those was every very pretty, and the presence check was
a complete failure because every vendor has another, accurate way to
provide lid status; ACPI was only ever a red herring for us poor Linux
folks.

But if you have some good use case and we can get some really really
good test coverage, these patches look nice.
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index f5b0d83..7ca9003 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -257,6 +257,14 @@  extern void intel_edp_link_config (struct intel_encoder *, int *, int *);
 extern bool intel_encoder_is_pch_edp(struct drm_encoder *encoder);
 
 /* intel_panel.c */
+struct intel_panel {
+	struct intel_connector *connector;
+	struct notifier_block lid_notifier;
+};
+extern int intel_panel_init(struct intel_panel *panel,
+			    struct intel_connector *connector);
+extern void intel_panel_fini(struct intel_panel *panel);
+
 extern void intel_fixed_panel_mode(struct drm_display_mode *fixed_mode,
 				   struct drm_display_mode *adjusted_mode);
 extern void intel_pch_panel_fitting(struct drm_device *dev,
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index f87adaa..20d6235 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -27,7 +27,6 @@ 
  *      Jesse Barnes <jesse.barnes@intel.com>
  */
 
-#include <acpi/button.h>
 #include <linux/dmi.h>
 #include <linux/i2c.h>
 #include <linux/slab.h>
@@ -38,13 +37,12 @@ 
 #include "intel_drv.h"
 #include "i915_drm.h"
 #include "i915_drv.h"
-#include <linux/acpi.h>
 
 /* Private structure for the integrated LVDS support */
 struct intel_lvds_connector {
 	struct intel_connector base;
+	struct intel_panel panel;
 
-	struct notifier_block lid_notifier;
 	struct drm_display_mode *fixed_mode;
 	struct edid *edid;
 
@@ -509,71 +507,6 @@  static int intel_lvds_connector_get_modes(struct drm_connector *connector)
 	return 1;
 }
 
-static int intel_no_modeset_on_lid_dmi_callback(const struct dmi_system_id *id)
-{
-	DRM_DEBUG_KMS("Skipping forced modeset for %s\n", id->ident);
-	return 1;
-}
-
-/* The GPU hangs up on these systems if modeset is performed on LID open */
-static const struct dmi_system_id intel_no_modeset_on_lid[] = {
-	{
-		.callback = intel_no_modeset_on_lid_dmi_callback,
-		.ident = "Toshiba Tecra A11",
-		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "TECRA A11"),
-		},
-	},
-
-	{ }	/* terminating entry */
-};
-
-/*
- * Lid events. Note the use of 'modeset_on_lid':
- *  - we set it on lid close, and reset it on open
- *  - we use it as a "only once" bit (ie we ignore
- *    duplicate events where it was already properly
- *    set/reset)
- *  - the suspend/resume paths will also set it to
- *    zero, since they restore the mode ("lid open").
- */
-static int intel_lid_notify(struct notifier_block *nb, unsigned long val,
-			    void *unused)
-{
-	struct intel_lvds_connector *lvds_connector =
-		container_of(nb, struct intel_lvds_connector, lid_notifier);
-	struct drm_device *dev = lvds_connector->base.base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-
-	/*
-	 * check and update the status of LVDS connector after receiving
-	 * the LID nofication event.
-	 */
-	lvds_connector->base.base.status =
-		lvds_connector->base.base.funcs->detect(&lvds_connector->base.base,
-							false);
-
-	/* Don't force modeset on machines where it causes a GPU lockup */
-	if (dmi_check_system(intel_no_modeset_on_lid))
-		return NOTIFY_OK;
-	if (!acpi_lid_open()) {
-		dev_priv->modeset_on_lid = 1;
-		return NOTIFY_OK;
-	}
-
-	if (!dev_priv->modeset_on_lid)
-		return NOTIFY_OK;
-
-	dev_priv->modeset_on_lid = 0;
-
-	mutex_lock(&dev->mode_config.mutex);
-	drm_helper_resume_force_mode(dev);
-	mutex_unlock(&dev->mode_config.mutex);
-
-	return NOTIFY_OK;
-}
-
 /**
  * intel_lvds_encoder_destroy - unregister and free LVDS structures
  * @connector: connector to free
@@ -586,8 +519,7 @@  static void intel_lvds_connector_destroy(struct drm_connector *connector)
 	struct intel_lvds_connector *lvds_connector =
 		to_lvds_connector(connector);
 
-	if (lvds_connector->lid_notifier.notifier_call)
-		acpi_lid_notifier_unregister(&lvds_connector->lid_notifier);
+	intel_panel_fini(&lvds_connector->panel);
 
 	drm_sysfs_connector_remove(connector);
 	drm_connector_cleanup(connector);
@@ -1063,11 +995,8 @@  out:
 		pwm |= PWM_PCH_ENABLE;
 		I915_WRITE(BLC_PWM_PCH_CTL1, pwm);
 	}
-	lvds_connector->lid_notifier.notifier_call = intel_lid_notify;
-	if (acpi_lid_notifier_register(&lvds_connector->lid_notifier)) {
-		DRM_DEBUG_KMS("lid notifier registration failed\n");
-		lvds_connector->lid_notifier.notifier_call = NULL;
-	}
+
+	intel_panel_init(&lvds_connector->panel, &lvds_connector->base);
 	drm_sysfs_connector_add(connector);
 	return true;
 
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index a06ff07..d2dc066 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -28,6 +28,10 @@ 
  *      Chris Wilson <chris@chris-wilson.co.uk>
  */
 
+#include <linux/acpi.h>
+#include <linux/dmi.h>
+#include <acpi/button.h>
+
 #include "intel_drv.h"
 
 #define PCI_LBPC 0xf4 /* legacy/combination backlight modes */
@@ -112,6 +116,94 @@  done:
 	dev_priv->pch_pf_size = (width << 16) | height;
 }
 
+/* Lid interactions */
+
+static int intel_no_modeset_on_lid_dmi_callback(const struct dmi_system_id *id)
+{
+	DRM_DEBUG_KMS("Skipping forced modeset for %s\n", id->ident);
+	return 1;
+}
+
+/* The GPU hangs up on these systems if modeset is performed on LID open */
+static const struct dmi_system_id intel_no_modeset_on_lid[] = {
+	{
+		.callback = intel_no_modeset_on_lid_dmi_callback,
+		.ident = "Toshiba Tecra A11",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "TECRA A11"),
+		},
+	},
+
+	{ }	/* terminating entry */
+};
+
+/*
+ * Lid events. Note the use of 'modeset_on_lid':
+ *  - we set it on lid close, and reset it on open
+ *  - we use it as a "only once" bit (ie we ignore
+ *    duplicate events where it was already properly
+ *    set/reset)
+ *  - the suspend/resume paths will also set it to
+ *    zero, since they restore the mode ("lid open").
+ */
+static int intel_panel_lid_notify(struct notifier_block *nb, unsigned long val,
+				  void *unused)
+{
+	struct intel_panel *panel =
+		container_of(nb, struct intel_panel, lid_notifier);
+	struct intel_connector *connector = panel->connector;
+	struct drm_device *dev = connector->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	/*
+	 * check and update the status of LVDS connector after receiving
+	 * the LID nofication event.
+	 */
+	connector->base.status =
+		connector->base.funcs->detect(&connector->base, false);
+
+	/* Don't force modeset on machines where it causes a GPU lockup */
+	if (dmi_check_system(intel_no_modeset_on_lid))
+		return NOTIFY_OK;
+	if (!acpi_lid_open()) {
+		dev_priv->modeset_on_lid = 1;
+		return NOTIFY_OK;
+	}
+
+	if (!dev_priv->modeset_on_lid)
+		return NOTIFY_OK;
+
+	dev_priv->modeset_on_lid = 0;
+
+	mutex_lock(&dev->mode_config.mutex);
+	drm_helper_resume_force_mode(dev);
+	mutex_unlock(&dev->mode_config.mutex);
+
+	return NOTIFY_OK;
+}
+
+int intel_panel_init(struct intel_panel *panel, struct intel_connector *connector)
+{
+	panel->connector = connector;
+
+	panel->lid_notifier.notifier_call = intel_panel_lid_notify;
+	if (acpi_lid_notifier_register(&panel->lid_notifier)) {
+		DRM_DEBUG_KMS("lid notifier registration failed\n");
+		panel->lid_notifier.notifier_call = NULL;
+	}
+
+	return 0;
+}
+
+void intel_panel_fini(struct intel_panel *panel)
+{
+	if (panel->lid_notifier.notifier_call)
+		acpi_lid_notifier_unregister(&panel->lid_notifier);
+}
+
+/* Panel backlight controls */
+
 static int is_backlight_combination_mode(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;