All of lore.kernel.org
 help / color / mirror / Atom feed
From: Paul Kocialkowski <paul.kocialkowski@linux.intel.com>
To: dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org,
	intel-gfx@lists.freedesktop.org
Cc: Daniel Vetter <daniel.vetter@intel.com>,
	Paul Kocialkowski <paul.kocialkowski@linux.intel.com>
Subject: [PATCH 2/2] drm/i915: Detect monitor change from EDID change after resume
Date: Mon, 24 Jul 2017 17:54:47 +0300	[thread overview]
Message-ID: <20170724145447.23449-2-paul.kocialkowski@linux.intel.com> (raw)
In-Reply-To: <20170724145447.23449-1-paul.kocialkowski@linux.intel.com>

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 <paul.kocialkowski@linux.intel.com>
---
 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);
-- 
2.13.2

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

WARNING: multiple messages have this Message-ID (diff)
From: Paul Kocialkowski <paul.kocialkowski@linux.intel.com>
To: dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org,
	intel-gfx@lists.freedesktop.org
Cc: Daniel Vetter <daniel.vetter@intel.com>,
	Jani Nikula <jani.nikula@linux.intel.com>,
	Sean Paul <seanpaul@chromium.org>,
	David Airlie <airlied@linux.ie>,
	Paul Kocialkowski <paul.kocialkowski@linux.intel.com>
Subject: [PATCH 2/2] drm/i915: Detect monitor change from EDID change after resume
Date: Mon, 24 Jul 2017 17:54:47 +0300	[thread overview]
Message-ID: <20170724145447.23449-2-paul.kocialkowski@linux.intel.com> (raw)
In-Reply-To: <20170724145447.23449-1-paul.kocialkowski@linux.intel.com>

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 <paul.kocialkowski@linux.intel.com>
---
 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);
-- 
2.13.2

  reply	other threads:[~2017-07-24 14:54 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-07-24 14:54 [PATCH 1/2] drm/edid: Add helper to detect whether EDID changed Paul Kocialkowski
2017-07-24 14:54 ` Paul Kocialkowski
2017-07-24 14:54 ` Paul Kocialkowski [this message]
2017-07-24 14:54   ` [PATCH 2/2] drm/i915: Detect monitor change from EDID change after resume Paul Kocialkowski
2017-07-24 16:00 ` [PATCH 1/2] drm/edid: Add helper to detect whether EDID changed Harry Wentland
2017-07-24 16:11 ` ✗ Fi.CI.BAT: warning for series starting with [1/2] " Patchwork
2017-07-25  6:53 ` [PATCH 1/2] " Daniel Vetter
2017-07-25  6:53   ` Daniel Vetter
2017-07-25  7:25   ` Paul Kocialkowski
2017-07-25  7:34     ` Daniel Vetter
2017-07-25  7:34       ` Daniel Vetter
2017-07-25  7:58       ` Paul Kocialkowski
2017-07-25  7:58         ` Paul Kocialkowski
2017-07-25  8:16         ` Daniel Vetter
2017-07-25 12:18           ` Paul Kocialkowski
2017-07-25 15:50             ` Daniel Vetter
2017-07-26 15:09               ` Paul Kocialkowski
2017-07-26 15:09                 ` Paul Kocialkowski

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170724145447.23449-2-paul.kocialkowski@linux.intel.com \
    --to=paul.kocialkowski@linux.intel.com \
    --cc=daniel.vetter@intel.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=intel-gfx@lists.freedesktop.org \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.