diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2011-06-07 14:23:51 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2011-06-07 16:54:57 +0100 |
commit | 265d94e0aa46b30a3198893544dd3619cc9145de (patch) | |
tree | 1f762b104148a13fd5c07dfb56d1e70614ae4216 | |
parent | ad5ead8257b7dda84a886461873d87831d43e663 (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.man | 10 | ||||
-rw-r--r-- | src/intel_module.c | 4 | ||||
-rw-r--r-- | src/sna/sna.h | 1 | ||||
-rw-r--r-- | src/sna/sna_display.c | 77 | ||||
-rw-r--r-- | src/sna/sna_driver.c | 67 | ||||
-rw-r--r-- | src/sna/sna_module.h | 2 |
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); |