Commit 05c72e77 authored by Ville Syrjälä's avatar Ville Syrjälä

drm/i915: Nuke the LVDS lid notifier

We broke the LVDS notifier resume thing in (presumably) commit
e2c8b870 ("drm/i915: Use atomic helpers for suspend, v2.") as
we no longer duplicate the current state in the LVDS notifier and
thus we never resume it properly either.

Instead of trying to fix it again let's just kill off the lid
notifier entirely. None of the machines tested thus far have
apparently needed it. Originally the lid notifier was added to
work around cases where the VBIOS was clobbering some of the
hardware state behind the driver's back, mostly on Thinkpads.
We now have a few report of Thinkpads working just fine without
the notifier. So maybe it was misdiagnosed originally, or
something else has changed (ACPI video stuff perhaps?).

If we do end up finding a machine where the VBIOS is still causing
problems I would suggest that we first try setting various bits in
the VBIOS scratch registers. There are several to choose from that
may instruct the VBIOS to steer clear.

With the notifier gone we'll also stop looking at the panel status
in ->detect().

v2: Nuke enum modeset_restore (Rodrigo)

Cc: stable@vger.kernel.org
Cc: Wolfgang Draxinger <wdraxinger.maillist@draxit.de>
Cc: Vito Caputo <vcaputo@pengaru.com>
Cc: kitsunyan <kitsunyan@airmail.cc>
Cc: Joonas Saarinen <jza@saunalahti.fi>
Tested-by: Vito Caputo <vcaputo@pengaru.com> # Thinkapd X61s
Tested-by: kitsunyan <kitsunyan@airmail.cc> # ThinkPad X200
Tested-by: Joonas Saarinen <jza@saunalahti.fi> # Fujitsu Siemens U9210
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=105902
References: https://lists.freedesktop.org/archives/intel-gfx/2018-June/169315.html
References: https://bugs.freedesktop.org/show_bug.cgi?id=21230
Fixes: e2c8b870 ("drm/i915: Use atomic helpers for suspend, v2.")
Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180717174216.22252-1-ville.syrjala@linux.intel.comReviewed-by: default avatarRodrigo Vivi <rodrigo.vivi@intel.com>
parent d78d3343
...@@ -900,7 +900,6 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv, ...@@ -900,7 +900,6 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv,
spin_lock_init(&dev_priv->uncore.lock); spin_lock_init(&dev_priv->uncore.lock);
mutex_init(&dev_priv->sb_lock); mutex_init(&dev_priv->sb_lock);
mutex_init(&dev_priv->modeset_restore_lock);
mutex_init(&dev_priv->av_mutex); mutex_init(&dev_priv->av_mutex);
mutex_init(&dev_priv->wm.wm_mutex); mutex_init(&dev_priv->wm.wm_mutex);
mutex_init(&dev_priv->pps_mutex); mutex_init(&dev_priv->pps_mutex);
...@@ -1570,11 +1569,6 @@ static int i915_drm_suspend(struct drm_device *dev) ...@@ -1570,11 +1569,6 @@ static int i915_drm_suspend(struct drm_device *dev)
struct pci_dev *pdev = dev_priv->drm.pdev; struct pci_dev *pdev = dev_priv->drm.pdev;
pci_power_t opregion_target_state; pci_power_t opregion_target_state;
/* ignore lid events during suspend */
mutex_lock(&dev_priv->modeset_restore_lock);
dev_priv->modeset_restore = MODESET_SUSPENDED;
mutex_unlock(&dev_priv->modeset_restore_lock);
disable_rpm_wakeref_asserts(dev_priv); disable_rpm_wakeref_asserts(dev_priv);
/* We do a lot of poking in a lot of registers, make sure they work /* We do a lot of poking in a lot of registers, make sure they work
...@@ -1770,10 +1764,6 @@ static int i915_drm_resume(struct drm_device *dev) ...@@ -1770,10 +1764,6 @@ static int i915_drm_resume(struct drm_device *dev)
intel_fbdev_set_suspend(dev, FBINFO_STATE_RUNNING, false); intel_fbdev_set_suspend(dev, FBINFO_STATE_RUNNING, false);
mutex_lock(&dev_priv->modeset_restore_lock);
dev_priv->modeset_restore = MODESET_DONE;
mutex_unlock(&dev_priv->modeset_restore_lock);
intel_opregion_notify_adapter(dev_priv, PCI_D0); intel_opregion_notify_adapter(dev_priv, PCI_D0);
enable_rpm_wakeref_asserts(dev_priv); enable_rpm_wakeref_asserts(dev_priv);
......
...@@ -1002,12 +1002,6 @@ struct i915_gem_mm { ...@@ -1002,12 +1002,6 @@ struct i915_gem_mm {
#define I915_ENGINE_WEDGED_TIMEOUT (60 * HZ) /* Reset but no recovery? */ #define I915_ENGINE_WEDGED_TIMEOUT (60 * HZ) /* Reset but no recovery? */
enum modeset_restore {
MODESET_ON_LID_OPEN,
MODESET_DONE,
MODESET_SUSPENDED,
};
#define DP_AUX_A 0x40 #define DP_AUX_A 0x40
#define DP_AUX_B 0x10 #define DP_AUX_B 0x10
#define DP_AUX_C 0x20 #define DP_AUX_C 0x20
...@@ -1730,8 +1724,6 @@ struct drm_i915_private { ...@@ -1730,8 +1724,6 @@ struct drm_i915_private {
unsigned long quirks; unsigned long quirks;
enum modeset_restore modeset_restore;
struct mutex modeset_restore_lock;
struct drm_atomic_state *modeset_restore_state; struct drm_atomic_state *modeset_restore_state;
struct drm_modeset_acquire_ctx reset_ctx; struct drm_modeset_acquire_ctx reset_ctx;
......
...@@ -44,8 +44,6 @@ ...@@ -44,8 +44,6 @@
/* Private structure for the integrated LVDS support */ /* Private structure for the integrated LVDS support */
struct intel_lvds_connector { struct intel_lvds_connector {
struct intel_connector base; struct intel_connector base;
struct notifier_block lid_notifier;
}; };
struct intel_lvds_pps { struct intel_lvds_pps {
...@@ -452,26 +450,9 @@ static bool intel_lvds_compute_config(struct intel_encoder *intel_encoder, ...@@ -452,26 +450,9 @@ static bool intel_lvds_compute_config(struct intel_encoder *intel_encoder,
return true; return true;
} }
/*
* Detect the LVDS connection.
*
* Since LVDS doesn't have hotlug, we use the lid as a proxy. Open means
* connected and closed means disconnected. We also send hotplug events as
* needed, using lid status notification from the input layer.
*/
static enum drm_connector_status static enum drm_connector_status
intel_lvds_detect(struct drm_connector *connector, bool force) intel_lvds_detect(struct drm_connector *connector, bool force)
{ {
struct drm_i915_private *dev_priv = to_i915(connector->dev);
enum drm_connector_status status;
DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
connector->base.id, connector->name);
status = intel_panel_detect(dev_priv);
if (status != connector_status_unknown)
return status;
return connector_status_connected; return connector_status_connected;
} }
...@@ -496,117 +477,6 @@ static int intel_lvds_get_modes(struct drm_connector *connector) ...@@ -496,117 +477,6 @@ static int intel_lvds_get_modes(struct drm_connector *connector)
return 1; return 1;
} }
static int intel_no_modeset_on_lid_dmi_callback(const struct dmi_system_id *id)
{
DRM_INFO("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':
* - we set it to MODESET_ON_LID_OPEN on lid close,
* and set it to MODESET_DONE on open
* - we use it as a "only once" bit (ie we ignore
* duplicate events where it was already properly set)
* - the suspend/resume paths will set it to
* MODESET_SUSPENDED and ignore the lid open event,
* because 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_connector *connector = &lvds_connector->base.base;
struct drm_device *dev = connector->dev;
struct drm_i915_private *dev_priv = to_i915(dev);
if (dev->switch_power_state != DRM_SWITCH_POWER_ON)
return NOTIFY_OK;
mutex_lock(&dev_priv->modeset_restore_lock);
if (dev_priv->modeset_restore == MODESET_SUSPENDED)
goto exit;
/*
* check and update the status of LVDS connector after receiving
* the LID nofication event.
*/
connector->status = connector->funcs->detect(connector, false);
/* Don't force modeset on machines where it causes a GPU lockup */
if (dmi_check_system(intel_no_modeset_on_lid))
goto exit;
if (!acpi_lid_open()) {
/* do modeset on next lid open event */
dev_priv->modeset_restore = MODESET_ON_LID_OPEN;
goto exit;
}
if (dev_priv->modeset_restore == MODESET_DONE)
goto exit;
/*
* Some old platform's BIOS love to wreak havoc while the lid is closed.
* We try to detect this here and undo any damage. The split for PCH
* platforms is rather conservative and a bit arbitrary expect that on
* those platforms VGA disabling requires actual legacy VGA I/O access,
* and as part of the cleanup in the hw state restore we also redisable
* the vga plane.
*/
if (!HAS_PCH_SPLIT(dev_priv))
intel_display_resume(dev);
dev_priv->modeset_restore = MODESET_DONE;
exit:
mutex_unlock(&dev_priv->modeset_restore_lock);
return NOTIFY_OK;
}
static int
intel_lvds_connector_register(struct drm_connector *connector)
{
struct intel_lvds_connector *lvds = to_lvds_connector(connector);
int ret;
ret = intel_connector_register(connector);
if (ret)
return ret;
lvds->lid_notifier.notifier_call = intel_lid_notify;
if (acpi_lid_notifier_register(&lvds->lid_notifier)) {
DRM_DEBUG_KMS("lid notifier registration failed\n");
lvds->lid_notifier.notifier_call = NULL;
}
return 0;
}
static void
intel_lvds_connector_unregister(struct drm_connector *connector)
{
struct intel_lvds_connector *lvds = to_lvds_connector(connector);
if (lvds->lid_notifier.notifier_call)
acpi_lid_notifier_unregister(&lvds->lid_notifier);
intel_connector_unregister(connector);
}
/** /**
* intel_lvds_destroy - unregister and free LVDS structures * intel_lvds_destroy - unregister and free LVDS structures
* @connector: connector to free * @connector: connector to free
...@@ -639,8 +509,8 @@ static const struct drm_connector_funcs intel_lvds_connector_funcs = { ...@@ -639,8 +509,8 @@ static const struct drm_connector_funcs intel_lvds_connector_funcs = {
.fill_modes = drm_helper_probe_single_connector_modes, .fill_modes = drm_helper_probe_single_connector_modes,
.atomic_get_property = intel_digital_connector_atomic_get_property, .atomic_get_property = intel_digital_connector_atomic_get_property,
.atomic_set_property = intel_digital_connector_atomic_set_property, .atomic_set_property = intel_digital_connector_atomic_set_property,
.late_register = intel_lvds_connector_register, .late_register = intel_connector_register,
.early_unregister = intel_lvds_connector_unregister, .early_unregister = intel_connector_unregister,
.destroy = intel_lvds_destroy, .destroy = intel_lvds_destroy,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state, .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
.atomic_duplicate_state = intel_digital_connector_duplicate_state, .atomic_duplicate_state = intel_digital_connector_duplicate_state,
...@@ -1114,8 +984,6 @@ void intel_lvds_init(struct drm_i915_private *dev_priv) ...@@ -1114,8 +984,6 @@ void intel_lvds_init(struct drm_i915_private *dev_priv)
* 2) check for VBT data * 2) check for VBT data
* 3) check to see if LVDS is already on * 3) check to see if LVDS is already on
* if none of the above, no panel * if none of the above, no panel
* 4) make sure lid is open
* if closed, act like it's not there for now
*/ */
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment