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

Chris Wilson ickle at kemper.freedesktop.org
Fri Oct 30 11:14:14 PDT 2015


 man/intel.man         |   18 +++++
 src/sna/sna_display.c |  153 +++++++++++++++++++++++++++++++-------------------
 2 files changed, 113 insertions(+), 58 deletions(-)

New commits:
commit 94d271b239d358f71ae0bcfcc31422a569d73d41
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Oct 30 18:07:37 2015 +0000

    sna: Allow pipes to be manually assigned to ZaphodHeads
    
    Assigning pipes to a driver instance is hard as not only do we have a
    limited number (so choosing which instances should share CRTCs requires
    user intervention) but also some pipes are limited by hardware to
    certain outputs and certain modes (and we do not have the full knowledge
    of the future configuration to be able to determine where to assign the
    CRTC). As usual, when there is no clear answer, punt it to the user.
    
    This expands the ZaphodHeads option to include an optional
    comma-separated pipe list followed by a colon before the output list,
    e.g.
    
    Section "Device"
            Identifier "Device0"
            Driver "intel"
            Option "ZaphodHeads" "1:LVDS"
            BusID "PCI:0:2:0"
            Screen 0
    EndSection
    
    Section "Device"
            Identifier "Device1"
            Driver "intel"
            Option "ZaphodHeads" "0,2:HDMI1,HDMI2,HDMI3"
            BusID "PCI:0:2:0"
            Screen 1
    EndSection
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/man/intel.man b/man/intel.man
index e1b7fb9..318a5b7 100644
--- a/man/intel.man
+++ b/man/intel.man
@@ -344,12 +344,28 @@ Default: 0
 .IP
 Specify the randr output(s) to use with zaphod mode for a particular driver
 instance.  If you set this option you must use it with all instances of the
-driver
+driver. By default, each head is assigned only one CRTC (which limits
+using multiple outputs with that head to cloned mode). CRTC can be manually
+assigned to individual heads by preceding the output names with a comma
+delimited list of pipe numbers followed by a colon. Note that different pipes
+may be limited in their functionality and some outputs may only work with
+different pipes.
 .br
 For example:
+
+.RS
 .B
 Option \*qZaphodHeads\*q \*qLVDS1,VGA1\*q
+
 will assign xrandr outputs LVDS1 and VGA1 to this instance of the driver.
+.RE
+
+.RS
+.B
+Option \*qZaphodHeads\*q \*q0,2:HDMI1,DP2\*q
+
+will assign xrandr outputs HDMI1 and DP2 and CRTCs 0 and 2 to this instance of the driver.
+.RE
 
 .SH OUTPUT CONFIGURATION
 On 830M and better chipsets, the driver supports runtime configuration of
diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index 7d06450..868d608 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -272,6 +272,81 @@ static bool is_zaphod(ScrnInfoPtr scrn)
 	return xf86IsEntityShared(scrn->entityList[0]);
 }
 
+static bool
+sna_zaphod_match(struct sna *sna, const char *output)
+{
+	const char *s, *colon;
+	char t[20];
+	unsigned int i = 0;
+
+	s = xf86GetOptValString(sna->Options, OPTION_ZAPHOD);
+	if (s == NULL)
+		return false;
+
+	colon = strchr(s, ':');
+	if (colon) /* Skip over the ZaphodPipes */
+		s = colon + 1;
+
+	do {
+		/* match any outputs in a comma list, stopping at whitespace */
+		switch (*s) {
+		case '\0':
+			t[i] = '\0';
+			return strcmp(t, output) == 0;
+
+		case ',':
+			t[i] ='\0';
+			if (strcmp(t, output) == 0)
+				return TRUE;
+			i = 0;
+			break;
+
+		case ' ':
+		case '\t':
+		case '\n':
+		case '\r':
+			break;
+
+		default:
+			t[i++] = *s;
+			break;
+		}
+
+		s++;
+	} while (i < sizeof(t));
+
+	return false;
+}
+
+static unsigned
+get_zaphod_crtcs(struct sna *sna)
+{
+	const char *str, *colon;
+	unsigned crtcs = 0;
+
+	str = xf86GetOptValString(sna->Options, OPTION_ZAPHOD);
+	if (str == NULL || (colon = strchr(str, ':')) == NULL) {
+		DBG(("%s: no zaphod pipes, using screen number: %x\n",
+		     __FUNCTION__,
+		     sna->scrn->confScreen->device->screen));
+		return 1 << sna->scrn->confScreen->device->screen;
+	}
+
+	DBG(("%s: ZaphodHeads='%s'\n", __FUNCTION__, str));
+	while (str < colon) {
+		char *end;
+		unsigned crtc = strtoul(str, &end, 0);
+		if (end == str)
+			break;
+		DBG(("%s: adding CRTC %d to zaphod pipes\n",
+		     __FUNCTION__, crtc));
+		crtcs |= 1 << crtc;
+		str = end + 1;
+	}
+	DBG(("%s: ZaphodPipes=%x\n", __FUNCTION__, crtcs));
+	return crtcs;
+}
+
 inline static unsigned count_to_mask(int x)
 {
 	return (1 << x) - 1;
@@ -3027,7 +3102,7 @@ sna_crtc_add(ScrnInfoPtr scrn, unsigned id)
 	struct sna_crtc *sna_crtc;
 	struct drm_i915_get_pipe_from_crtc_id get_pipe;
 
-	DBG(("%s(%d)\n", __FUNCTION__, id));
+	DBG(("%s(%d): is-zaphod? %d\n", __FUNCTION__, id, is_zaphod(scrn)));
 
 	sna_crtc = calloc(sizeof(struct sna_crtc), 1);
 	if (sna_crtc == NULL)
@@ -3049,7 +3124,7 @@ sna_crtc_add(ScrnInfoPtr scrn, unsigned id)
 	sna_crtc->flags |= get_pipe.pipe << 8;
 
 	if (is_zaphod(scrn) &&
-	    scrn->confScreen->device->screen != get_pipe.pipe) {
+	    (get_zaphod_crtcs(sna) & (1 << get_pipe.pipe)) == 0) {
 		free(sna_crtc);
 		return true;
 	}
@@ -4112,43 +4187,6 @@ static const char * const output_names[] = {
 };
 
 static bool
-sna_zaphod_match(const char *s, const char *output)
-{
-	char t[20];
-	unsigned int i = 0;
-
-	do {
-		/* match any outputs in a comma list, stopping at whitespace */
-		switch (*s) {
-		case '\0':
-			t[i] = '\0';
-			return strcmp(t, output) == 0;
-
-		case ',':
-			t[i] ='\0';
-			if (strcmp(t, output) == 0)
-				return TRUE;
-			i = 0;
-			break;
-
-		case ' ':
-		case '\t':
-		case '\n':
-		case '\r':
-			break;
-
-		default:
-			t[i++] = *s;
-			break;
-		}
-
-		s++;
-	} while (i < sizeof(t));
-
-	return false;
-}
-
-static bool
 output_ignored(ScrnInfoPtr scrn, const char *name)
 {
 	char monitor_name[64];
@@ -4541,25 +4579,26 @@ sna_output_add(struct sna *sna, unsigned id, unsigned serial)
 	}
 
 	if (is_zaphod(scrn)) {
-		const char *str;
+		unsigned zaphod_crtcs;
 
-		str = xf86GetOptValString(sna->Options, OPTION_ZAPHOD);
-		if (str && !sna_zaphod_match(str, name)) {
-			DBG(("%s: zaphod mismatch, want %s, have %s\n", __FUNCTION__, str, name));
+		if (!sna_zaphod_match(sna, name)) {
+			DBG(("%s: zaphod mismatch, want %s, have %s\n",
+			     __FUNCTION__,
+			     xf86GetOptValString(sna->Options, OPTION_ZAPHOD),
+			     name));
 			return 0;
 		}
 
-		if ((possible_crtcs & (1 << scrn->confScreen->device->screen)) == 0) {
-			if (str) {
-				xf86DrvMsg(scrn->scrnIndex, X_ERROR,
-					   "%s is an invalid output for screen (pipe) %d\n",
-					   name, scrn->confScreen->device->screen);
-				return -1;
-			} else
-				return 0;
+		zaphod_crtcs = get_zaphod_crtcs(sna);
+		possible_crtcs &= zaphod_crtcs;
+		if (possible_crtcs == 0) {
+			xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+				   "%s is an invalid output for screen %d\n",
+				   name, scrn->confScreen->device->screen);
+			return -1;
 		}
 
-		possible_crtcs = 1;
+		possible_crtcs >>= ffs(zaphod_crtcs) - 1;
 	}
 
 	sna_output = calloc(sizeof(struct sna_output), 1);
@@ -4599,16 +4638,16 @@ sna_output_add(struct sna *sna, unsigned id, unsigned serial)
 	/* Construct name from topology, and recheck if output is acceptable */
 	path = name_from_path(sna, sna_output, name);
 	if (path) {
-		const char *str;
-
 		if (output_ignored(scrn, name)) {
 			len = 0;
 			goto skip;
 		}
 
-		str = xf86GetOptValString(sna->Options, OPTION_ZAPHOD);
-		if (str && !sna_zaphod_match(str, name)) {
-			DBG(("%s: zaphod mismatch, want %s, have %s\n", __FUNCTION__, str, name));
+		if (!sna_zaphod_match(sna, name)) {
+			DBG(("%s: zaphod mismatch, want %s, have %s\n",
+			     __FUNCTION__,
+			     xf86GetOptValString(sna->Options, OPTION_ZAPHOD),
+			     name));
 			len = 0;
 			goto skip;
 		}


More information about the xorg-commit mailing list