summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2011-06-07 14:23:51 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2011-06-07 16:54:57 +0100
commit265d94e0aa46b30a3198893544dd3619cc9145de (patch)
tree1f762b104148a13fd5c07dfb56d1e70614ae4216
parentad5ead8257b7dda84a886461873d87831d43e663 (diff)
sna: Add zaphod support
Zaphod support is a rudimentary method for creating an Xserver with multiple screens from a single device. The Device is instantiated, with a duplication of its resources, as many as required up to a maximum of the number of its outputs, and each instance is attached to a Screen and added to the ServerLayout. A Device can be bound to a selection of outputs using a comma separated list of RandR names. Note: in general, this is not the preferred solution! And will be superseded by per-crtc-pixmaps in RandR-1.4. For example, the following xorg.conf fragment creates an XServer with two screens, one attached to the LVDS panel on the laptop, and the other to any external output: Section "Device" Identifier "Intel0" Driver "intel" BusID "PCI:0:2:0" Option "ZaphodHeads" "LVDS1" Screen 0 EndSection Section "Device" Identifier "Intel1" Driver "intel" BusID "PCI:0:2:0" Option "ZaphodHeads" "DVI1,VGA1" Screen 1 EndSection Section "Screen" Identifier "Screen0" Device "Intel0" EndSection Section "Screen" Identifier "Screen1" Device "Intel1" EndSection Section "ServerLayout" Identifier "default" Screen "Screen0" Screen "Screen1" EndSection Based on a patch by Ben Skegs <bskeggs@redhat.com> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--man/intel.man10
-rw-r--r--src/intel_module.c4
-rw-r--r--src/sna/sna.h1
-rw-r--r--src/sna/sna_display.c77
-rw-r--r--src/sna/sna_driver.c67
-rw-r--r--src/sna/sna_module.h2
6 files changed, 133 insertions, 28 deletions
diff --git a/man/intel.man b/man/intel.man
index ab46db2a..e5e05724 100644
--- a/man/intel.man
+++ b/man/intel.man
@@ -222,6 +222,16 @@ This option controls whether the driver automatically notifies
applications when monitors are connected or disconnected.
.IP
Default: enabled.
+.BI "Option \*qZaphodHeads\*q \*q" string \*q
+.IP
+Specify the randr output(s) to use with zaphod mode for a particular driver
+instance. If you this option you must use it with all instances of the
+driver
+.br
+For example:
+.B
+Option \*qZaphodHeads\*q \*qLVDS1,VGA1\*q
+will assign xrandr outputs LVDS1 and VGA0 to this instance of the driver.
.SH OUTPUT CONFIGURATION
On 830M and better chipsets, the driver supports runtime configuration of
diff --git a/src/intel_module.c b/src/intel_module.c
index 12097dfb..bec3d0f1 100644
--- a/src/intel_module.c
+++ b/src/intel_module.c
@@ -363,12 +363,12 @@ static Bool intel_pci_probe(DriverPtr driver,
case PCI_CHIP_SANDYBRIDGE_M_GT2_PLUS:
case PCI_CHIP_SANDYBRIDGE_S_GT:
#endif
- sna_init_scrn(scrn);
+ sna_init_scrn(scrn, entity_num);
break;
#endif
default:
#if SNA_DEFAULT
- sna_init_scrn(scrn);
+ sna_init_scrn(scrn, entity_num);
#else
intel_init_scrn(scrn);
#endif
diff --git a/src/sna/sna.h b/src/sna/sna.h
index cb4b61ae..e36ef481 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -201,6 +201,7 @@ enum {
OPTION_THROTTLE,
OPTION_RELAXED_FENCING,
OPTION_VMAP,
+ OPTION_ZAPHOD,
};
enum {
diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index d27eafde..847d8212 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -1231,6 +1231,43 @@ static const char *output_names[] = {
"eDP",
};
+static bool
+sna_zaphod_match(ScrnInfoPtr scrn, const char *s, const char *output)
+{
+ char t[20];
+ 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 void
sna_output_init(ScrnInfoPtr scrn, struct sna_mode *mode, int num)
{
@@ -1240,6 +1277,7 @@ sna_output_init(ScrnInfoPtr scrn, struct sna_mode *mode, int num)
drmModeEncoderPtr kencoder;
struct sna_output *sna_output;
const char *output_name;
+ const char *s;
char name[32];
koutput = drmModeGetConnector(sna->kgem.fd,
@@ -1248,10 +1286,8 @@ sna_output_init(ScrnInfoPtr scrn, struct sna_mode *mode, int num)
return;
kencoder = drmModeGetEncoder(sna->kgem.fd, koutput->encoders[0]);
- if (!kencoder) {
- drmModeFreeConnector(koutput);
- return;
- }
+ if (!kencoder)
+ goto cleanup_connector;
if (koutput->connector_type < ARRAY_SIZE(output_names))
output_name = output_names[koutput->connector_type];
@@ -1259,20 +1295,22 @@ sna_output_init(ScrnInfoPtr scrn, struct sna_mode *mode, int num)
output_name = "UNKNOWN";
snprintf(name, 32, "%s%d", output_name, koutput->connector_type_id);
- output = xf86OutputCreate (scrn, &sna_output_funcs, name);
- if (!output) {
- drmModeFreeEncoder(kencoder);
- drmModeFreeConnector(koutput);
- return;
+ if (xf86IsEntityShared(scrn->entityList[0])) {
+ s = xf86GetOptValString(sna->Options, OPTION_ZAPHOD);
+ if (s && !sna_zaphod_match(scrn, s, name)) {
+ ErrorF("output '%s' not matched for zaphod '%s'\n",
+ name, s);
+ goto cleanup_encoder;
+ }
}
+ output = xf86OutputCreate(scrn, &sna_output_funcs, name);
+ if (!output)
+ goto cleanup_encoder;
+
sna_output = calloc(sizeof(struct sna_output), 1);
- if (!sna_output) {
- xf86OutputDestroy(output);
- drmModeFreeConnector(koutput);
- drmModeFreeEncoder(kencoder);
- return;
- }
+ if (!sna_output)
+ goto cleanup_output;
sna_output->output_id = mode->mode_res->connectors[num];
sna_output->mode_output = koutput;
@@ -1294,6 +1332,15 @@ sna_output_init(ScrnInfoPtr scrn, struct sna_mode *mode, int num)
sna_output->output = output;
list_add(&sna_output->link, &mode->outputs);
+
+ return;
+
+cleanup_output:
+ xf86OutputDestroy(output);
+cleanup_connector:
+ drmModeFreeConnector(koutput);
+cleanup_encoder:
+ drmModeFreeEncoder(kencoder);
}
struct sna_visit_set_pixmap_window {
diff --git a/src/sna/sna_driver.c b/src/sna/sna_driver.c
index b0df9aa5..bbd1d494 100644
--- a/src/sna/sna_driver.c
+++ b/src/sna/sna_driver.c
@@ -81,6 +81,7 @@ static OptionInfoRec sna_options[] = {
{OPTION_THROTTLE, "Throttle", OPTV_BOOLEAN, {0}, TRUE},
{OPTION_RELAXED_FENCING, "UseRelaxedFencing", OPTV_BOOLEAN, {0}, TRUE},
{OPTION_VMAP, "UseVmap", OPTV_BOOLEAN, {0}, TRUE},
+ {OPTION_ZAPHOD, "ZaphodHeads", OPTV_STRING, {0}, FALSE},
{-1, NULL, OPTV_NONE, {0}, FALSE}
};
@@ -257,18 +258,41 @@ static Bool sna_get_early_options(ScrnInfoPtr scrn)
return TRUE;
}
+struct sna_device {
+ int fd;
+ int open_count;
+};
+static int sna_device_key;
+
+static inline struct sna_device *sna_device(ScrnInfoPtr scrn)
+{
+ return xf86GetEntityPrivate(scrn->entityList[0], sna_device_key)->ptr;
+}
+
+static inline void sna_set_device(ScrnInfoPtr scrn, struct sna_device *dev)
+{
+ xf86GetEntityPrivate(scrn->entityList[0], sna_device_key)->ptr = dev;
+}
+
static int sna_open_drm_master(ScrnInfoPtr scrn)
{
+ struct sna_device *dev;
struct sna *sna = to_sna(scrn);
- struct pci_device *dev = sna->PciInfo;
+ struct pci_device *pci = sna->PciInfo;
drmSetVersion sv;
struct drm_i915_getparam gp;
int err, val;
char busid[20];
int fd;
+ dev = sna_device(scrn);
+ if (dev) {
+ dev->open_count++;
+ return dev->fd;
+ }
+
snprintf(busid, sizeof(busid), "pci:%04x:%02x:%02x.%d",
- dev->domain, dev->bus, dev->dev, dev->func);
+ pci->domain, pci->bus, pci->dev, pci->func);
fd = drmOpen("i915", busid);
if (fd == -1) {
@@ -305,15 +329,26 @@ static int sna_open_drm_master(ScrnInfoPtr scrn)
return -1;
}
+ dev = malloc(sizeof(*dev));
+ if (dev) {
+ dev->fd = fd;
+ dev->open_count = 1;
+ sna_set_device(scrn, dev);
+ }
+
return fd;
}
-static void sna_close_drm_master(struct sna *sna)
+static void sna_close_drm_master(ScrnInfoPtr scrn)
{
- if (sna && sna->kgem.fd > 0) {
- drmClose(sna->kgem.fd);
- sna->kgem.fd = -1;
- }
+ struct sna_device *dev = sna_device(scrn);
+
+ if (--dev->open_count)
+ return;
+
+ drmClose(dev->fd);
+ sna_set_device(scrn, NULL);
+ free(dev);
}
static void sna_selftest(void)
@@ -321,7 +356,6 @@ static void sna_selftest(void)
sna_damage_selftest();
}
-
/**
* This is called before ScreenInit to do any require probing of screen
* configuration.
@@ -811,12 +845,13 @@ static void sna_free_screen(int scrnIndex, int flags)
if (sna) {
sna_mode_fini(sna);
- sna_close_drm_master(sna);
free(sna);
scrn->driverPrivate = NULL;
}
+ sna_close_drm_master(scrn);
+
if (xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
vgaHWFreeHWRec(xf86Screens[scrnIndex]);
}
@@ -911,8 +946,12 @@ static Bool sna_pm_event(int scrnIndex, pmEvent event, Bool undo)
return TRUE;
}
-void sna_init_scrn(ScrnInfoPtr scrn)
+void sna_init_scrn(ScrnInfoPtr scrn, int entity_num)
{
+ EntityInfoPtr entity;
+
+ sna_device_key = xf86AllocateEntityPrivateIndex();
+
scrn->PreInit = sna_pre_init;
scrn->ScreenInit = sna_screen_init;
scrn->SwitchMode = sna_switch_mode;
@@ -922,4 +961,12 @@ void sna_init_scrn(ScrnInfoPtr scrn)
scrn->FreeScreen = sna_free_screen;
scrn->ValidMode = sna_valid_mode;
scrn->PMEvent = sna_pm_event;
+
+ xf86SetEntitySharable(scrn->entityList[0]);
+
+ entity = xf86GetEntityInfo(entity_num);
+ xf86SetEntityInstanceForScreen(scrn,
+ entity->index,
+ xf86GetNumEntityInstances(entity->index)-1);
+ free(entity);
}
diff --git a/src/sna/sna_module.h b/src/sna/sna_module.h
index 9b14acc3..97d5dd5e 100644
--- a/src/sna/sna_module.h
+++ b/src/sna/sna_module.h
@@ -1,3 +1,3 @@
const OptionInfoRec *sna_available_options(int chipid, int busid);
-void sna_init_scrn(ScrnInfoPtr scrn);
+void sna_init_scrn(ScrnInfoPtr scrn, int entity_num);