All of lore.kernel.org
 help / color / mirror / Atom feed
From: Paulo Zanoni <przanoni@gmail.com>
To: intel-gfx@lists.freedesktop.org
Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
Subject: [PATCH 3/3] drm/i915: Set the digital port encoder personality during modeset
Date: Tue,  7 Jan 2014 14:55:55 -0200	[thread overview]
Message-ID: <1389113755-2021-3-git-send-email-przanoni@gmail.com> (raw)
In-Reply-To: <1389113755-2021-1-git-send-email-przanoni@gmail.com>

From: Damien Lespiau <damien.lespiau@intel.com>

The ->detect() vfunc of connectors is usually responsible for setting the
encoder type on intel_digital_ports when a hotplug event happens.

However we sometimes want to force a modeset on a specific connector:
  - the user can ask the SETCRTC ioctl to use a connector that isn't
    marked as connected (because we never received a hotplug event for it).
    This can be also used in tests to do a modeset without the need of a
    plugged-in monitor.
  - the command line video= option can be used to force modesets, eg.:
    video=HDMI-A-1:1024x768e

So, before we try to do anything with the DDI encoder as part of a modeset,
we need to ensure that the personality of the encoder matches the selected
connector.

v2: Made by Paulo:
  - Return false if we have more than one connector
  - WARN in case it's not eDP/DP/HDMI
  - Don't break error strings in pieces
  - Change the "status == connected" message from DRM_ERROR to
    DRM_DEBUG_KMS
  - Don't store+use the old encoder->type at compute_config
  - Add bugzilla reference
  - Add testcase reference
v3: Made by Paulo:
  - WARN in case "connectors > 1", since we have a patch that should
    catch this case earlier

Testcase: igt/kms_setmode/clone-exclusive-crtc
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=68463
Tested-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_ddi.c | 94 ++++++++++++++++++++++++++++++++++++++--
 1 file changed, 91 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 1488b28..4ec1665 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -1512,18 +1512,106 @@ static void intel_ddi_destroy(struct drm_encoder *encoder)
 	intel_dp_encoder_destroy(encoder);
 }
 
+/*
+ * The ->detect() vfunc of connectors is usually responsible for setting the
+ * encoder type on intel_digital_ports when a hotplug event happens.
+ *
+ * However we sometimes want to force a modeset on a specific connector:
+ *   - the user can ask the SETCRTC ioctl to use a connector that isn't marked
+ *     as connected (because we never received a hotplug event for it).
+ *     This can be also used in tests to do a modeset without the need of a
+ *     plugged-in monitor.
+ *   - the command line video= option can be used to force modesets, eg.:
+ *     video=HDMI-A-1:1024x768e
+ *
+ * So, before we try to do anything with the DDI encoder as part of a modeset,
+ * we need to ensure that the personality of the encoder matches the selected
+ * connector.
+ */
+static bool
+intel_ddi_ensure_encoder_type(struct intel_encoder *encoder)
+{
+	struct drm_device *dev = encoder->base.dev;
+	struct intel_connector *connector;
+	int connectors = 0;
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list,
+			    base.head) {
+		int connector_type, old_encoder_type, new_encoder_type;
+		int port;
+
+		if (connector->new_encoder != encoder)
+			continue;
+
+		connectors++;
+		if (WARN_ON(connectors > 1))
+			return false;
+
+		connector_type = connector->base.connector_type;
+		old_encoder_type = encoder->type;
+		switch (connector_type) {
+		case DRM_MODE_CONNECTOR_HDMIA:
+		case DRM_MODE_CONNECTOR_HDMIB:
+			new_encoder_type = INTEL_OUTPUT_HDMI;
+			break;
+		case DRM_MODE_CONNECTOR_DisplayPort:
+			new_encoder_type = INTEL_OUTPUT_DISPLAYPORT;
+			break;
+		case DRM_MODE_CONNECTOR_eDP:
+			continue;
+		default:
+			WARN(1, "DRM connector type %d\n", connector_type);
+			continue;
+		}
+
+		if (old_encoder_type == new_encoder_type)
+			continue;
+
+		port = intel_ddi_get_encoder_port(encoder);
+
+		if (old_encoder_type == INTEL_OUTPUT_EDP) {
+			DRM_ERROR("Can't change DDI %c personality to %s, it's an eDP DDI\n",
+				  port_name(port),
+				  intel_output_name(new_encoder_type));
+			return false;
+		}
+
+		if (connector->base.status == connector_status_connected) {
+			DRM_DEBUG_KMS("Can't change DDI %c personality to %s, it has a connected %s device\n",
+				      port_name(port),
+				      intel_output_name(new_encoder_type),
+				      intel_output_name(old_encoder_type));
+			return false;
+		}
+
+		DRM_DEBUG_KMS("Changing DDI %c from %s to %s\n",
+			      port_name(port),
+			      intel_output_name(old_encoder_type),
+			      intel_output_name(new_encoder_type));
+
+		encoder->type = new_encoder_type;
+	}
+
+	return true;
+}
+
 static bool intel_ddi_compute_config(struct intel_encoder *encoder,
 				     struct intel_crtc_config *pipe_config)
 {
-	int type = encoder->type;
 	int port = intel_ddi_get_encoder_port(encoder);
+	int ret;
+
+	ret = intel_ddi_ensure_encoder_type(encoder);
+	if (!ret)
+		return false;
 
-	WARN(type == INTEL_OUTPUT_UNKNOWN, "compute_config() on unknown output!\n");
+	WARN(encoder->type == INTEL_OUTPUT_UNKNOWN,
+	     "compute_config() on unknown output!\n");
 
 	if (port == PORT_A)
 		pipe_config->cpu_transcoder = TRANSCODER_EDP;
 
-	if (type == INTEL_OUTPUT_HDMI)
+	if (encoder->type == INTEL_OUTPUT_HDMI)
 		return intel_hdmi_compute_config(encoder, pipe_config);
 	else
 		return intel_dp_compute_config(encoder, pipe_config);
-- 
1.8.4.2

  parent reply	other threads:[~2014-01-07 16:56 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-01-07 16:55 [PATCH 1/3] drm/i915: don't set modes for 2 connectors on the same encoder Paulo Zanoni
2014-01-07 16:55 ` [PATCH 2/3] drm/i915: Introduce new intel_output_name() Paulo Zanoni
2014-01-08  9:51   ` Jani Nikula
2014-01-08 14:18     ` [PATCH 2/3 v2] " Damien Lespiau
2014-01-08 14:38       ` Jani Nikula
2014-01-07 16:55 ` Paulo Zanoni [this message]
2014-01-10 18:13   ` [PATCH 3/3] drm/i915: Set the digital port encoder personality during modeset Damien Lespiau
2014-01-13 18:03     ` [PATCH 3/3 v4] " Damien Lespiau
2014-01-14  9:02       ` Daniel Vetter
2014-01-10 16:17 ` [PATCH 1/3] drm/i915: don't set modes for 2 connectors on the same encoder Damien Lespiau

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=1389113755-2021-3-git-send-email-przanoni@gmail.com \
    --to=przanoni@gmail.com \
    --cc=intel-gfx@lists.freedesktop.org \
    --cc=paulo.r.zanoni@intel.com \
    /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.