From 19e1dc8f6ea6d7ff5ba4a5caa0e2f40a47879408 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 22 Jul 2015 03:56:13 +0100 Subject: modesetting: add zaphod support (v3) This adds zaphod and ZaphodHeads support to the the in-server modesetting driver. this is based on a request from Mario, and on the current radeon driver, along with some patches from Mario to bring things up to the state of the art in Zaphod. v2: fixup vblank fd registring. v3: squash Mario's fixes. modesetting: Allow/Fix use of multiple ZaphodHead outputs per x-screen. modesetting: Take shift in crtc positions for ZaphodHeads configs into account. modesetting: Add ZaphodHeads description to man page. small cleanups (airlied). Reviewed-and-tested-by: Mario Kleiner Reviewed-by: Alex Deucher Signed-off-by: Dave Airlie --- hw/xfree86/drivers/modesetting/driver.c | 193 +++++++++++++++-------- hw/xfree86/drivers/modesetting/driver.h | 35 ++-- hw/xfree86/drivers/modesetting/drmmode_display.c | 97 ++++++++++-- hw/xfree86/drivers/modesetting/drmmode_display.h | 5 + hw/xfree86/drivers/modesetting/modesetting.man | 10 ++ hw/xfree86/drivers/modesetting/vblank.c | 23 ++- 6 files changed, 261 insertions(+), 102 deletions(-) diff --git a/hw/xfree86/drivers/modesetting/driver.c b/hw/xfree86/drivers/modesetting/driver.c index 324b8bd64..80abcdf8d 100644 --- a/hw/xfree86/drivers/modesetting/driver.c +++ b/hw/xfree86/drivers/modesetting/driver.c @@ -118,24 +118,17 @@ static SymTabRec Chipsets[] = { {-1, NULL} }; -typedef enum { - OPTION_SW_CURSOR, - OPTION_DEVICE_PATH, - OPTION_SHADOW_FB, - OPTION_ACCEL_METHOD, - OPTION_PAGEFLIP, -} modesettingOpts; - static const OptionInfoRec Options[] = { {OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE}, {OPTION_DEVICE_PATH, "kmsdev", OPTV_STRING, {0}, FALSE}, {OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE}, {OPTION_ACCEL_METHOD, "AccelMethod", OPTV_STRING, {0}, FALSE}, {OPTION_PAGEFLIP, "PageFlip", OPTV_BOOLEAN, {0}, FALSE}, + {OPTION_ZAPHOD_HEADS, "ZaphodHeads", OPTV_STRING, {0}, FALSE}, {-1, NULL, OPTV_NONE, {0}, FALSE} }; -int modesettingEntityIndex = -1; +int ms_entity_index = -1; static MODULESETUPPROTO(Setup); @@ -187,6 +180,15 @@ Identify(int flags) Chipsets); } +modesettingEntPtr ms_ent_priv(ScrnInfoPtr scrn) +{ + DevUnion *pPriv; + modesettingPtr ms = modesettingPTR(scrn); + pPriv = xf86GetEntityPrivate(ms->pEnt->index, + ms_entity_index); + return pPriv->ptr; +} + static int open_hw(const char *dev) { @@ -374,12 +376,40 @@ ms_platform_probe(DriverPtr driver, if (probe_hw(path, dev)) { scrn = xf86AllocateScreen(driver, scr_flags); + if (xf86IsEntitySharable(entity_num)) + xf86SetEntityShared(entity_num); xf86AddEntityToScreen(scrn, entity_num); ms_setup_scrn_hooks(scrn); xf86DrvMsg(scrn->scrnIndex, X_INFO, "using drv %s\n", path ? path : "default device"); + + { + DevUnion *pPriv; + EntityInfoPtr pEnt; + modesettingEntPtr pMSEnt; + + xf86SetEntitySharable(entity_num); + + if (ms_entity_index == -1) + ms_entity_index = xf86AllocateEntityPrivateIndex(); + + pEnt = xf86GetEntityInfo(entity_num); + pPriv = xf86GetEntityPrivate(pEnt->index, + ms_entity_index); + + xf86SetEntityInstanceForScreen(scrn, pEnt->index, xf86GetNumEntityInstances(pEnt->index) - 1); + + if (!pPriv->ptr) { + pPriv->ptr = xnfcalloc(sizeof(modesettingEntRec), 1); + pMSEnt = pPriv->ptr; + } else { + pMSEnt = pPriv->ptr; + } + pMSEnt->platform_dev = dev; + } + } return scrn != NULL; @@ -596,19 +626,25 @@ FreeRec(ScrnInfoPtr pScrn) pScrn->driverPrivate = NULL; if (ms->fd > 0) { + modesettingEntPtr ms_ent; int ret; - if (ms->pEnt->location.type == BUS_PCI) - ret = drmClose(ms->fd); - else + ms_ent = ms_ent_priv(pScrn); + ms_ent->fd_ref--; + if (!ms_ent->fd_ref) { + if (ms->pEnt->location.type == BUS_PCI) + ret = drmClose(ms->fd); + else #ifdef XF86_PDEV_SERVER_FD - if (!(ms->pEnt->location.type == BUS_PLATFORM && - (ms->pEnt->location.id.plat->flags & XF86_PDEV_SERVER_FD))) + if (!(ms->pEnt->location.type == BUS_PLATFORM && + (ms->pEnt->location.id.plat->flags & XF86_PDEV_SERVER_FD))) #endif - ret = close(ms->fd); - (void) ret; + ret = close(ms->fd); + (void) ret; + ms_ent->fd = 0; + } } - free(ms->Options); + free(ms->drmmode.Options); free(ms); } @@ -617,7 +653,7 @@ static void try_enable_glamor(ScrnInfoPtr pScrn) { modesettingPtr ms = modesettingPTR(pScrn); - const char *accel_method_str = xf86GetOptValString(ms->Options, + const char *accel_method_str = xf86GetOptValString(ms->drmmode.Options, OPTION_ACCEL_METHOD); Bool do_glamor = (!accel_method_str || strcmp(accel_method_str, "glamor") == 0); @@ -659,60 +695,26 @@ try_enable_glamor(ScrnInfoPtr pScrn) #endif static Bool -PreInit(ScrnInfoPtr pScrn, int flags) +ms_get_drm_master_fd(ScrnInfoPtr pScrn) { - modesettingPtr ms; - rgb defaultWeight = { 0, 0, 0 }; EntityInfoPtr pEnt; - EntPtr msEnt = NULL; + modesettingPtr ms; + modesettingEntPtr ms_ent; char *BusID = NULL; - const char *devicename; - uint64_t value = 0; - int ret; - int bppflags; - int defaultdepth, defaultbpp; - - if (pScrn->numEntities != 1) - return FALSE; - - pEnt = xf86GetEntityInfo(pScrn->entityList[0]); - - if (flags & PROBE_DETECT) { - return FALSE; - } - - /* Allocate driverPrivate */ - if (!GetRec(pScrn)) - return FALSE; ms = modesettingPTR(pScrn); - ms->SaveGeneration = -1; - ms->pEnt = pEnt; - - pScrn->displayWidth = 640; /* default it */ + ms_ent = ms_ent_priv(pScrn); - /* Allocate an entity private if necessary */ - if (xf86IsEntityShared(pScrn->entityList[0])) { - msEnt = xf86GetEntityPrivate(pScrn->entityList[0], - modesettingEntityIndex)->ptr; - ms->entityPrivate = msEnt; - } - else - ms->entityPrivate = NULL; + pEnt = ms->pEnt; - if (xf86IsEntityShared(pScrn->entityList[0])) { - if (xf86IsPrimInitDone(pScrn->entityList[0])) { - /* do something */ - } - else { - xf86SetPrimInitDone(pScrn->entityList[0]); - } + if (ms_ent->fd) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + " reusing fd for second head\n"); + ms->fd = ms_ent->fd; + ms_ent->fd_ref++; + return TRUE; } - pScrn->monitor = pScrn->confScreen->monitor; - pScrn->progClock = TRUE; - pScrn->rgbBits = 8; - #if XSERVER_PLATFORM_BUS if (pEnt->location.type == BUS_PLATFORM) { #ifdef XF86_PDEV_SERVER_FD @@ -749,12 +751,61 @@ PreInit(ScrnInfoPtr pScrn, int flags) ms->fd = drmOpen(NULL, BusID); } else { + const char *devicename; devicename = xf86FindOptionValue(ms->pEnt->device->options, "kmsdev"); ms->fd = open_hw(devicename); } if (ms->fd < 0) return FALSE; + ms_ent->fd = ms->fd; + ms_ent->fd_ref = 1; + return TRUE; +} + +static Bool +PreInit(ScrnInfoPtr pScrn, int flags) +{ + modesettingPtr ms; + rgb defaultWeight = { 0, 0, 0 }; + EntityInfoPtr pEnt; + uint64_t value = 0; + int ret; + int bppflags; + int defaultdepth, defaultbpp; + + if (pScrn->numEntities != 1) + return FALSE; + + pEnt = xf86GetEntityInfo(pScrn->entityList[0]); + + if (flags & PROBE_DETECT) { + return FALSE; + } + + /* Allocate driverPrivate */ + if (!GetRec(pScrn)) + return FALSE; + + ms = modesettingPTR(pScrn); + ms->SaveGeneration = -1; + ms->pEnt = pEnt; + ms->drmmode.is_secondary = FALSE; + pScrn->displayWidth = 640; /* default it */ + + if (xf86IsEntityShared(pScrn->entityList[0])) { + if (xf86IsPrimInitDone(pScrn->entityList[0])) + ms->drmmode.is_secondary = TRUE; + else + xf86SetPrimInitDone(pScrn->entityList[0]); + } + + pScrn->monitor = pScrn->confScreen->monitor; + pScrn->progClock = TRUE; + pScrn->rgbBits = 8; + + if (!ms_get_drm_master_fd(pScrn)) + return FALSE; ms->drmmode.fd = ms->fd; pScrn->capabilities = 0; @@ -794,17 +845,17 @@ PreInit(ScrnInfoPtr pScrn, int flags) /* Process the options */ xf86CollectOptions(pScrn, NULL); - if (!(ms->Options = malloc(sizeof(Options)))) + if (!(ms->drmmode.Options = malloc(sizeof(Options)))) return FALSE; - memcpy(ms->Options, Options, sizeof(Options)); - xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, ms->Options); + memcpy(ms->drmmode.Options, Options, sizeof(Options)); + xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, ms->drmmode.Options); if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight)) return FALSE; if (!xf86SetDefaultVisual(pScrn, -1)) return FALSE; - if (xf86ReturnOptValBool(ms->Options, OPTION_SW_CURSOR, FALSE)) { + if (xf86ReturnOptValBool(ms->drmmode.Options, OPTION_SW_CURSOR, FALSE)) { ms->drmmode.sw_cursor = TRUE; } @@ -823,7 +874,7 @@ PreInit(ScrnInfoPtr pScrn, int flags) if (ms->drmmode.glamor) { ms->drmmode.pageflip = - xf86ReturnOptValBool(ms->Options, OPTION_PAGEFLIP, TRUE); + xf86ReturnOptValBool(ms->drmmode.Options, OPTION_PAGEFLIP, TRUE); } else { Bool prefer_shadow = TRUE; @@ -832,7 +883,7 @@ PreInit(ScrnInfoPtr pScrn, int flags) prefer_shadow = !!value; } - ms->drmmode.shadow_enable = xf86ReturnOptValBool(ms->Options, + ms->drmmode.shadow_enable = xf86ReturnOptValBool(ms->drmmode.Options, OPTION_SHADOW_FB, prefer_shadow); @@ -1277,6 +1328,10 @@ CloseScreen(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); modesettingPtr ms = modesettingPTR(pScrn); + modesettingEntPtr ms_ent = ms_ent_priv(pScrn); + + /* Clear mask of assigned crtc's in this generation */ + ms_ent->assigned_crtcs = 0; #ifdef GLAMOR if (ms->drmmode.glamor) { diff --git a/hw/xfree86/drivers/modesetting/driver.h b/hw/xfree86/drivers/modesetting/driver.h index 9ae4966fd..14137c112 100644 --- a/hw/xfree86/drivers/modesetting/driver.h +++ b/hw/xfree86/drivers/modesetting/driver.h @@ -43,13 +43,28 @@ #include "drmmode_display.h" #define DRV_ERROR(msg) xf86DrvMsg(pScrn->scrnIndex, X_ERROR, msg); - -typedef struct { - int lastInstance; - int refCount; - ScrnInfoPtr pScrn_1; - ScrnInfoPtr pScrn_2; -} EntRec, *EntPtr; +#define MS_LOGLEVEL_DEBUG 4 + +typedef enum { + OPTION_SW_CURSOR, + OPTION_DEVICE_PATH, + OPTION_SHADOW_FB, + OPTION_ACCEL_METHOD, + OPTION_PAGEFLIP, + OPTION_ZAPHOD_HEADS, +} modesettingOpts; + +typedef struct +{ + int fd; + int fd_ref; + unsigned long fd_wakeup_registered; /* server generation for which fd has been registered for wakeup handling */ + int fd_wakeup_ref; + unsigned int assigned_crtcs; +#ifdef XSERVER_PLATFORM_BUS + struct xf86_platform_device *platform_dev; +#endif +} modesettingEntRec, *modesettingEntPtr; typedef void (*ms_drm_handler_proc)(uint64_t frame, uint64_t usec, @@ -74,8 +89,6 @@ struct ms_drm_queue { typedef struct _modesettingRec { int fd; - EntPtr entityPrivate; - int Chipset; EntityInfoPtr pEnt; #if XSERVER_LIBPCIACCESS @@ -88,9 +101,6 @@ typedef struct _modesettingRec { Bool noAccel; CloseScreenProcPtr CloseScreen; - /* Broken-out options. */ - OptionInfoPtr Options; - unsigned int SaveGeneration; CreateScreenResourcesProcPtr createScreenResources; @@ -114,6 +124,7 @@ typedef struct _modesettingRec { } modesettingRec, *modesettingPtr; #define modesettingPTR(p) ((modesettingPtr)((p)->driverPrivate)) +modesettingEntPtr ms_ent_priv(ScrnInfoPtr scrn); uint32_t ms_drm_queue_alloc(xf86CrtcPtr crtc, void *data, diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c b/hw/xfree86/drivers/modesetting/drmmode_display.c index 6a13660dd..4d8892fd5 100644 --- a/hw/xfree86/drivers/modesetting/drmmode_display.c +++ b/hw/xfree86/drivers/modesetting/drmmode_display.c @@ -52,6 +52,39 @@ static Bool drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height); +static Bool +drmmode_zaphod_string_matches(ScrnInfoPtr scrn, const char *s, char *output_name) +{ + int i = 0; + char s1[20]; + + do { + switch(*s) { + case ',': + s1[i] = '\0'; + i = 0; + if (strcmp(s1, output_name) == 0) + return TRUE; + break; + case ' ': + case '\t': + case '\n': + case '\r': + break; + default: + s1[i] = *s; + i++; + break; + } + } while(*s++); + + s1[i] = '\0'; + if (strcmp(s1, output_name) == 0) + return TRUE; + + return FALSE; +} + int drmmode_bo_destroy(drmmode_ptr drmmode, drmmode_bo *bo) { @@ -788,15 +821,16 @@ drmmode_crtc_vblank_pipe(int crtc_id) return 0; } -static void +static unsigned int drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res, int num) { xf86CrtcPtr crtc; drmmode_crtc_private_ptr drmmode_crtc; + modesettingEntPtr ms_ent = ms_ent_priv(pScrn); crtc = xf86CrtcCreate(pScrn, &drmmode_crtc_funcs); if (crtc == NULL) - return; + return 0; drmmode_crtc = xnfcalloc(sizeof(drmmode_crtc_private_rec), 1); drmmode_crtc->mode_crtc = @@ -804,6 +838,13 @@ drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res drmmode_crtc->drmmode = drmmode; drmmode_crtc->vblank_pipe = drmmode_crtc_vblank_pipe(num); crtc->driver_private = drmmode_crtc; + + /* Mark num'th crtc as in use on this device. */ + ms_ent->assigned_crtcs |= (1 << num); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, MS_LOGLEVEL_DEBUG, + "Allocated crtc nr. %d to this screen.\n", num); + + return 1; } static xf86OutputStatus @@ -1345,8 +1386,8 @@ drmmode_create_name(ScrnInfoPtr pScrn, drmModeConnectorPtr koutput, char *name, snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], koutput->connector_type_id - 1); } -static void -drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res, int num, Bool dynamic) +static unsigned int +drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res, int num, Bool dynamic, int crtcshift) { xf86OutputPtr output; xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); @@ -1357,11 +1398,11 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r char name[32]; int i; drmModePropertyBlobPtr path_blob = NULL; - + const char *s; koutput = drmModeGetConnector(drmmode->fd, mode_res->connectors[num]); if (!koutput) - return; + return 0; for (i = 0; i < koutput->count_props; i++) { props = drmModeGetProperty(drmmode->fd, koutput->props[i]); @@ -1392,7 +1433,7 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r drmmode_output = output->driver_private; drmmode_output->output_id = mode_res->connectors[num]; drmmode_output->mode_output = koutput; - return; + return 1; } } @@ -1408,6 +1449,18 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r } } + if (xf86IsEntityShared(pScrn->entityList[0])) { + if ((s = xf86GetOptValString(drmmode->Options, OPTION_ZAPHOD_HEADS))) { + if (!drmmode_zaphod_string_matches(pScrn, s, name)) + goto out_free_encoders; + } else { + if (!drmmode->is_secondary && (num != 0)) + goto out_free_encoders; + else if (drmmode->is_secondary && (num != 1)) + goto out_free_encoders; + } + } + output = xf86OutputCreate(pScrn, &drmmode_output_funcs, name); if (!output) { goto out_free_encoders; @@ -1433,7 +1486,7 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r output->possible_crtcs = 0x7f; for (i = 0; i < koutput->count_encoders; i++) { - output->possible_crtcs &= kencoders[i]->possible_crtcs; + output->possible_crtcs &= kencoders[i]->possible_crtcs >> crtcshift; } /* work out the possible clones later */ output->possible_clones = 0; @@ -1452,7 +1505,8 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r if (dynamic) output->randr_output = RROutputCreate(xf86ScrnToScreen(pScrn), output->name, strlen(output->name), output); - return; + return 1; + out_free_encoders: if (kencoders) { for (i = 0; i < koutput->count_encoders; i++) @@ -1461,6 +1515,7 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r } drmModeFreeConnector(koutput); + return 0; } static uint32_t @@ -1682,10 +1737,13 @@ static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = { Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp) { + modesettingEntPtr ms_ent = ms_ent_priv(pScrn); int i; int ret; uint64_t value = 0; + unsigned int crtcs_needed = 0; drmModeResPtr mode_res; + int crtcshift; /* check for dumb capability */ ret = drmGetCap(drmmode->fd, DRM_CAP_DUMB_BUFFER, &value); @@ -1703,15 +1761,26 @@ drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp) if (!mode_res) return FALSE; + crtcshift = ffs(ms_ent->assigned_crtcs ^ 0xffffffff) - 1; + for (i = 0; i < mode_res->count_connectors; i++) + crtcs_needed += drmmode_output_init(pScrn, drmmode, mode_res, i, FALSE, + crtcshift); + + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, MS_LOGLEVEL_DEBUG, + "Up to %d crtcs needed for screen.\n", crtcs_needed); + xf86CrtcSetSizeRange(pScrn, 320, 200, mode_res->max_width, mode_res->max_height); for (i = 0; i < mode_res->count_crtcs; i++) if (!xf86IsEntityShared(pScrn->entityList[0]) || - pScrn->confScreen->device->screen == i) - drmmode_crtc_init(pScrn, drmmode, mode_res, i); + (crtcs_needed && !(ms_ent->assigned_crtcs & (1 << i)))) + crtcs_needed -= drmmode_crtc_init(pScrn, drmmode, mode_res, i); - for (i = 0; i < mode_res->count_connectors; i++) - drmmode_output_init(pScrn, drmmode, mode_res, i, FALSE); + /* All ZaphodHeads outputs provided with matching crtcs? */ + if (xf86IsEntityShared(pScrn->entityList[0]) && (crtcs_needed > 0)) + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "%d ZaphodHeads crtcs unavailable. Some outputs will stay off.\n", + crtcs_needed); /* workout clones */ drmmode_clones_init(pScrn, drmmode, mode_res); @@ -1941,7 +2010,7 @@ drmmode_handle_uevents(int fd, void *closure) continue; changed = TRUE; - drmmode_output_init(scrn, drmmode, mode_res, i, 1); + drmmode_output_init(scrn, drmmode, mode_res, i, TRUE, 0); } if (changed) { diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.h b/hw/xfree86/drivers/modesetting/drmmode_display.h index fe363c577..fca68a6fe 100644 --- a/hw/xfree86/drivers/modesetting/drmmode_display.h +++ b/hw/xfree86/drivers/modesetting/drmmode_display.h @@ -60,6 +60,9 @@ typedef struct { drmmode_bo front_bo; Bool sw_cursor; + /* Broken-out options. */ + OptionInfoPtr Options; + Bool glamor; Bool shadow_enable; /** Is Option "PageFlip" enabled? */ @@ -82,6 +85,8 @@ typedef struct { DevPrivateKeyRec pixmapPrivateKeyRec; Bool reverse_prime_offload_mode; + + Bool is_secondary; } drmmode_rec, *drmmode_ptr; typedef struct { diff --git a/hw/xfree86/drivers/modesetting/modesetting.man b/hw/xfree86/drivers/modesetting/modesetting.man index 9cb27d728..e13a4e259 100644 --- a/hw/xfree86/drivers/modesetting/modesetting.man +++ b/hw/xfree86/drivers/modesetting/modesetting.man @@ -50,6 +50,16 @@ Enable or disable use of the shadow framebuffer layer. Default: on. .BI "Option \*qAccelMethod\*q \*q" string \*q One of \*qglamor\*q or \*qnone\*q. Default: glamor .TP +.BI "Option \*qZaphodHeads\*q \*q" string \*q +Specify the RandR output(s) to use with zaphod mode for a particular driver +instance. If you use this option you must use this option for all instances +of the driver. +.br +For example: +.B +Option \*qZaphodHeads\*q \*qLVDS,VGA-0\*q +will assign xrandr outputs LVDS and VGA-0 to this instance of the driver. +.TP .SH "SEE ALSO" __xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__) diff --git a/hw/xfree86/drivers/modesetting/vblank.c b/hw/xfree86/drivers/modesetting/vblank.c index 0b7bf9d73..77e0848e7 100644 --- a/hw/xfree86/drivers/modesetting/vblank.c +++ b/hw/xfree86/drivers/modesetting/vblank.c @@ -381,7 +381,7 @@ ms_vblank_screen_init(ScreenPtr screen) { ScrnInfoPtr scrn = xf86ScreenToScrn(screen); modesettingPtr ms = modesettingPTR(scrn); - + modesettingEntPtr ms_ent = ms_ent_priv(scrn); xorg_list_init(&ms_drm_queue); ms->event_context.version = DRM_EVENT_CONTEXT_VERSION; @@ -392,9 +392,14 @@ ms_vblank_screen_init(ScreenPtr screen) * feedback on every server generation, so perform the * registration within ScreenInit and not PreInit. */ - AddGeneralSocket(ms->fd); - RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA, - ms_drm_wakeup_handler, screen); + if (ms_ent->fd_wakeup_registered != serverGeneration) { + AddGeneralSocket(ms->fd); + RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA, + ms_drm_wakeup_handler, screen); + ms_ent->fd_wakeup_registered = serverGeneration; + ms_ent->fd_wakeup_ref = 1; + } else + ms_ent->fd_wakeup_ref++; return TRUE; } @@ -404,10 +409,14 @@ ms_vblank_close_screen(ScreenPtr screen) { ScrnInfoPtr scrn = xf86ScreenToScrn(screen); modesettingPtr ms = modesettingPTR(scrn); + modesettingEntPtr ms_ent = ms_ent_priv(scrn); ms_drm_abort_scrn(scrn); - RemoveBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA, - ms_drm_wakeup_handler, screen); - RemoveGeneralSocket(ms->fd); + if (ms_ent->fd_wakeup_registered == serverGeneration && + !--ms_ent->fd_wakeup_ref) { + RemoveBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA, + ms_drm_wakeup_handler, screen); + RemoveGeneralSocket(ms->fd); + } } -- cgit v1.2.3