From patchwork Mon Jul 24 14:54:47 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Kocialkowki X-Patchwork-Id: 9859651 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 8FC6A60349 for ; Mon, 24 Jul 2017 14:55:11 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 81A18283ED for ; Mon, 24 Jul 2017 14:55:11 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 769D028419; Mon, 24 Jul 2017 14:55:11 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 0F8B6283ED for ; Mon, 24 Jul 2017 14:55:11 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id DF3F26E2DC; Mon, 24 Jul 2017 14:55:09 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mga06.intel.com (mga06.intel.com [134.134.136.31]) by gabe.freedesktop.org (Postfix) with ESMTPS id 9846D6E2D5; Mon, 24 Jul 2017 14:55:07 +0000 (UTC) Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga104.jf.intel.com with ESMTP; 24 Jul 2017 07:55:06 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos; i="5.40,407,1496127600"; d="scan'208"; a="1154738519" Received: from linux.intel.com ([10.54.29.200]) by orsmga001.jf.intel.com with ESMTP; 24 Jul 2017 07:55:07 -0700 Received: from workstation.fi.intel.com (workstation.fi.intel.com [10.237.68.144]) by linux.intel.com (Postfix) with ESMTP id 251DC580130; Mon, 24 Jul 2017 07:55:03 -0700 (PDT) From: Paul Kocialkowski To: dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, intel-gfx@lists.freedesktop.org Date: Mon, 24 Jul 2017 17:54:47 +0300 Message-Id: <20170724145447.23449-2-paul.kocialkowski@linux.intel.com> X-Mailer: git-send-email 2.13.2 In-Reply-To: <20170724145447.23449-1-paul.kocialkowski@linux.intel.com> References: <20170724145447.23449-1-paul.kocialkowski@linux.intel.com> Cc: David Airlie , Daniel Vetter Subject: [Intel-gfx] [PATCH 2/2] drm/i915: Detect monitor change from EDID change after resume X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP This introduces a dedicated work and related helpers to detect whether a monitor was replaced by another one during suspend. This detection is based on EDID change detection, using the associated generic drm helper. This requires storing more information to the intel_connector structure, such as the i2c adapter required to get the EDID. Support for this is introduced for DP, HDMI and VGA. Signed-off-by: Paul Kocialkowski --- drivers/gpu/drm/i915/i915_drv.c | 2 ++ drivers/gpu/drm/i915/i915_drv.h | 5 ++++ drivers/gpu/drm/i915/intel_crt.c | 3 +++ drivers/gpu/drm/i915/intel_display.c | 50 ++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_dp.c | 3 +++ drivers/gpu/drm/i915/intel_drv.h | 6 +++++ drivers/gpu/drm/i915/intel_hdmi.c | 3 +++ 7 files changed, 72 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 3ac8215c0e36..b3cf4112fc65 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1702,6 +1702,8 @@ static int i915_drm_resume(struct drm_device *dev) intel_display_resume(dev); + intel_edid_changes_detect(dev); + drm_kms_helper_poll_enable(dev); /* diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index b051122c960b..2c189a5b714e 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3904,6 +3904,11 @@ intel_display_capture_error_state(struct drm_i915_private *dev_priv); extern void intel_display_print_error_state(struct drm_i915_error_state_buf *e, struct intel_display_error_state *error); +/* edid change */ +void intel_edid_change_init(struct intel_connector *connector, + struct i2c_adapter *adapter); +void intel_edid_changes_detect(struct drm_device *dev); + int sandybridge_pcode_read(struct drm_i915_private *dev_priv, u32 mbox, u32 *val); int sandybridge_pcode_write(struct drm_i915_private *dev_priv, u32 mbox, u32 val); int skl_pcode_request(struct drm_i915_private *dev_priv, u32 mbox, u32 request, diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 84a1f5e85153..63e2184a6ea4 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -925,6 +925,9 @@ void intel_crt_init(struct drm_i915_private *dev_priv) */ crt->force_hotplug_required = 0; + intel_edid_change_init(intel_connector, + intel_gmbus_get_adapter(dev_priv, dev_priv->vbt.crt_ddc_pin)); + /* * TODO: find a proper way to discover whether we need to set the the * polarity and link reversal bits or not, instead of relying on the diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 6c823cc02db3..69e306759a02 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -15016,3 +15016,53 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m, } #endif + +static void intel_edid_change_work_func(struct work_struct *work) +{ + struct intel_connector *connector = + container_of(work, struct intel_connector, edid_change_work); + bool changed; + + changed = drm_check_edid_changed(&connector->base, connector->adapter); + if (changed) { + DRM_DEBUG_KMS("[CONNECTOR:%d:%s] EDID change detected\n", + connector->base.base.id, connector->base.name); + + drm_kms_helper_hotplug_event(connector->base.dev); + } +} + +/** + * intel_edid_change_init - init the EDID change data + * @connector: DRM connector device to use + * @adapter: i2c adapter + * + * Store the i2c adapter and initialize the EDID change detection work. + */ +void intel_edid_change_init(struct intel_connector *connector, + struct i2c_adapter *adapter) +{ + connector->adapter = adapter; + + INIT_WORK(&connector->edid_change_work, intel_edid_change_work_func); +} + +/** + * intel_edid_changes_detect - detect EDID changes to connectors + * @dev: DRM device to get connectors from + * + * Schedule the EDID detection change work for all registered connectors. + */ +void intel_edid_changes_detect(struct drm_device *dev) +{ + struct intel_connector *connector; + struct drm_connector_list_iter conn_iter; + + drm_connector_list_iter_begin(dev, &conn_iter); + for_each_intel_connector_iter(connector, &conn_iter) { + if (!connector->adapter) + continue; + + schedule_work(&connector->edid_change_work); + } +} diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 2d42d09428c9..bc4dbb076096 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -6063,6 +6063,9 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, goto fail; } + if (!is_edp(intel_dp)) + intel_edid_change_init(intel_connector, &intel_dp->aux.ddc); + intel_dp_add_properties(intel_dp, connector); /* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 021cc5487853..47d350d2f993 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -319,6 +319,12 @@ struct intel_connector { struct edid *edid; struct edid *detect_edid; + /* I2C adapter to retrieve the EDID. */ + struct i2c_adapter *adapter; + + /* Work to detect EDID change. */ + struct work_struct edid_change_work; + /* since POLL and HPD connectors may use the same HPD line keep the native state of connector->polled in case hotplug storm detection changes it */ u8 polled; diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 2f831cfdd243..a6ce77f81668 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -1909,6 +1909,9 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, else intel_connector->get_hw_state = intel_connector_get_hw_state; + intel_edid_change_init(intel_connector, + intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus)); + intel_hdmi_add_properties(intel_hdmi, connector); intel_connector_attach_encoder(intel_connector, intel_encoder);