xf86-video-intel: src/intel_display.c src/sna/sna_display.c

Chris Wilson ickle at kemper.freedesktop.org
Fri Oct 12 01:47:20 PDT 2012


 src/intel_display.c   |   57 +++++++++++++++++++++++++++++++++++++++++++++++++-
 src/sna/sna_display.c |   32 ++++++++++++++++++++++++++++
 2 files changed, 88 insertions(+), 1 deletion(-)

New commits:
commit 1ec41590c9d142a77a2fdcfcd9a762aca99d9d86
Author: Paulo Zanoni <paulo.r.zanoni at intel.com>
Date:   Thu Oct 11 18:10:17 2012 -0300

    Fix possible_clones computation for shared encoders between outputs
    
    Libdrm's possible_clones is a mask of encoders. Xorg's possible_clones
    is a mask of outputs, so we just can't do the following:
    
      output->possible_clones = kencoder->possible_clones;
    
    This is a problem on Haswell because, at least with the current
    patches floating on the mailing list, there is more than one connector
    per encoder.
    
    This patch writes the code to properly translate libdrm's encoder mask
    into Xorg's output mask.
    
    Signed-off-by: Paulo Zanoni <paulo.r.zanoni at intel.com>
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/intel_display.c b/src/intel_display.c
index b2a5904..d58e6e0 100644
--- a/src/intel_display.c
+++ b/src/intel_display.c
@@ -1435,7 +1435,6 @@ intel_output_init(ScrnInfoPtr scrn, struct intel_mode *mode, int num)
 		intel_output_backlight_init(output);
 
 	output->possible_crtcs = kencoder->possible_crtcs;
-	output->possible_clones = kencoder->possible_clones;
 	output->interlaceAllowed = TRUE;
 
 	intel_output->output = output;
@@ -1680,6 +1679,60 @@ drm_wakeup_handler(pointer data, int err, pointer p)
 		drmHandleEvent(mode->fd, &mode->event_context);
 }
 
+static drmModeEncoderPtr
+intel_get_kencoder(struct intel_mode *mode, int num)
+{
+	struct intel_output *iterator;
+	int id = mode->mode_res->encoders[num];
+
+	list_for_each_entry(iterator, &mode->outputs, link)
+		if (iterator->mode_encoder->encoder_id == id)
+			return iterator->mode_encoder;
+
+	return NULL;
+}
+
+/*
+ * Libdrm's possible_clones is a mask of encoders, Xorg's possible_clones is a
+ * mask of outputs. This function sets Xorg's possible_clones based on the
+ * values read from libdrm.
+ */
+static void
+intel_compute_possible_clones(ScrnInfoPtr scrn, struct intel_mode *mode)
+{
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+	struct intel_output *intel_output, *clone;
+	drmModeEncoderPtr cloned_encoder;
+	uint32_t mask;
+	int i, j, k;
+	CARD32 possible_clones;
+
+	for (i = 0; i < config->num_output; i++) {
+		possible_clones = 0;
+		intel_output = config->output[i]->driver_private;
+
+		mask = intel_output->mode_encoder->possible_clones;
+		for (j = 0; mask != 0; j++, mask >>= 1) {
+
+			if ((mask & 1) == 0)
+				continue;
+
+			cloned_encoder = intel_get_kencoder(mode, j);
+			if (!cloned_encoder)
+				continue;
+
+			for (k = 0; k < config->num_output; k++) {
+				clone = config->output[k]->driver_private;
+				if (clone->mode_encoder->encoder_id ==
+				    cloned_encoder->encoder_id)
+					possible_clones |= (1 << k);
+			}
+		}
+
+		config->output[i]->possible_clones = possible_clones;
+	}
+}
+
 Bool intel_mode_pre_init(ScrnInfoPtr scrn, int fd, int cpp)
 {
 	intel_screen_private *intel = intel_get_screen_private(scrn);
@@ -1716,6 +1769,8 @@ Bool intel_mode_pre_init(ScrnInfoPtr scrn, int fd, int cpp)
 	for (i = 0; i < mode->mode_res->count_connectors; i++)
 		intel_output_init(scrn, mode, i);
 
+	intel_compute_possible_clones(scrn, mode);
+
 #ifdef INTEL_PIXMAP_SHARING
 	xf86ProviderSetup(scrn, NULL, "Intel");
 #endif
diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index fc5cbfc..ed32375 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -2291,6 +2291,35 @@ cleanup_connector:
 	drmModeFreeConnector(koutput);
 }
 
+/* The kernel reports possible encoder clones, whereas X uses a list of
+ * possible connector clones. This is works when we have a 1:1 mapping
+ * between encoders and connectors, but breaks for Haswell which has a pair
+ * of DP/HDMI connectors hanging off a single encoder.
+ */
+static void
+sna_mode_compute_possible_clones(ScrnInfoPtr scrn)
+{
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+	unsigned clones[32] = { 0 };
+	int i, j;
+
+	assert(config->num_output <= 32);
+
+	/* Convert from encoder numbering to output numbering */
+	for (i = 0; i < config->num_output; i++) {
+		unsigned mask = config->output[i]->possible_clones;
+		for (j = 0; mask != 0; j++, mask >>= 1) {
+			if ((mask & 1) == 0)
+				continue;
+
+			clones[j] |= 1 << i;
+		}
+	}
+
+	for (i = 0; i < config->num_output; i++)
+		config->output[i]->possible_clones = clones[i];
+}
+
 struct sna_visit_set_pixmap_window {
 	PixmapPtr old, new;
 };
@@ -2574,6 +2603,9 @@ bool sna_mode_pre_init(ScrnInfoPtr scrn, struct sna *sna)
 	for (i = 0; i < mode->kmode->count_connectors; i++)
 		sna_output_init(scrn, mode, i);
 
+	if (!xf86IsEntityShared(scrn->entityList[0]))
+		sna_mode_compute_possible_clones(scrn);
+
 #if HAS_PIXMAP_SHARING
 	xf86ProviderSetup(scrn, NULL, "Intel");
 #endif


More information about the xorg-commit mailing list