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);