summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2015-10-30 18:07:37 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2015-10-30 18:07:37 +0000
commit94d271b239d358f71ae0bcfcc31422a569d73d41 (patch)
treee4eeece817959fd8ff608471335fc7373d77c4dd
parentd78200e53e6e5b889a71f79c103aa4e1ba148c95 (diff)
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@chris-wilson.co.uk>
-rw-r--r--man/intel.man18
-rw-r--r--src/sna/sna_display.c153
2 files changed, 113 insertions, 58 deletions
diff --git a/man/intel.man b/man/intel.man
index e1b7fb93..318a5b71 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 7d06450e..868d6087 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;
}