... in preparation for enabling it from eDP as well. Signed-off-by: Chris Wilson <ch...@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.bar...@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 <ch...@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 _______________________________________________ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx