summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-11-02 09:29:55 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2009-11-02 09:29:55 -0800
commitc9354c85c1c7bac788ce57d3c17f2016c1c45b1d (patch)
treeb51e70799226546e0efd494cfdbf64237dbd2265
parentb6727b12dd2ffb4a890eb5b13a298230c29ba45d (diff)
downloadlinux-3.10-c9354c85c1c7bac788ce57d3c17f2016c1c45b1d.tar.gz
linux-3.10-c9354c85c1c7bac788ce57d3c17f2016c1c45b1d.tar.bz2
linux-3.10-c9354c85c1c7bac788ce57d3c17f2016c1c45b1d.zip
i915: fix intel graphics suspend breakage due to resume/lid event confusion
In commit c1c7af60892070e4b82ad63bbfb95ae745056de0 ("drm/i915: force mode set at lid open time") the intel graphics driver was taught to restore the LVDS mode on lid open. That caused problems with interaction with the suspend/resume code, which commonly runs at the same time (suspend is often caused by the lid close event, while lid open is commonly a resume event), which was worked around with in commit 06891e27a9b5dba5268bb80e41a283f51335afe7 ("drm/i915: fix suspend/resume breakage in lid notifier"). However, in the meantime the lid event code had also grown a user event notifier (commit 06324194eee97a51b5f172270df49ec39192d6cc: "drm/i915: generate a KMS uevent at lid open/close time"), and now _that_ causes problems with suspend/resume and some versions of Xorg reacting to those uevents by setting the mode. So this effectively reverts that commit 06324194ee, and makes the lid open protection logic against suspend/resume more explicit. This fixes at least one laptop. See http://bugzilla.kernel.org/show_bug.cgi?id=14484 for more details. Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org> Cc: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com> Cc: Eric Anholt <eric@anholt.net> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c5
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h2
-rw-r--r--drivers/gpu/drm/i915/intel_lvds.c25
3 files changed, 24 insertions, 8 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index b93814c0d3e..7f436ec075f 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -89,7 +89,8 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state)
pci_set_power_state(dev->pdev, PCI_D3hot);
}
- dev_priv->suspended = 1;
+ /* Modeset on resume, not lid events */
+ dev_priv->modeset_on_lid = 0;
return 0;
}
@@ -124,7 +125,7 @@ static int i915_resume(struct drm_device *dev)
drm_helper_resume_force_mode(dev);
}
- dev_priv->suspended = 0;
+ dev_priv->modeset_on_lid = 0;
return ret;
}
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 6035d3dae85..c5df2234418 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -274,7 +274,7 @@ typedef struct drm_i915_private {
struct drm_i915_display_funcs display;
/* Register state */
- bool suspended;
+ bool modeset_on_lid;
u8 saveLBB;
u32 saveDSPACNTR;
u32 saveDSPBCNTR;
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index 98ae3d73577..808bbe412ba 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -656,6 +656,15 @@ static int intel_lvds_get_modes(struct drm_connector *connector)
return 0;
}
+/*
+ * 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)
{
@@ -663,13 +672,19 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val,
container_of(nb, struct drm_i915_private, lid_notifier);
struct drm_device *dev = dev_priv->dev;
- if (acpi_lid_open() && !dev_priv->suspended) {
- mutex_lock(&dev->mode_config.mutex);
- drm_helper_resume_force_mode(dev);
- mutex_unlock(&dev->mode_config.mutex);
+ if (!acpi_lid_open()) {
+ dev_priv->modeset_on_lid = 1;
+ return NOTIFY_OK;
}
- drm_sysfs_hotplug_event(dev_priv->dev);
+ 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;
}