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

Chris Wilson
2011-04-22T09:19:26Z

... 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(-)

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;
--
1.7.4.1