On Tue, Aug 4, 2015 at 6:18 PM, Mario Kleiner <mario.kleiner...@gmail.com> wrote: > Hi Dave, > > thanks for implementing this! > > This one is > > Reviewed-and-tested-by: Mario Kleiner <mario.kleiner...@gmail.com> > > I tested on intel/nouveau/radeon-kms with different combos of one/two/three > x-screen with one/two/three ZaphohHeads outputs and also regular > single-x-screen multi-display. > > In combination with the additional series of patches i just sent out for > handling > 1 output per x-screen and for some nvidia cards, on top of your > patch, this works fine on all tested setups. > > Maybe we could squash all the Zaphod patches into one patch, throwing away > my commit messages, so we have one nice patch to show the state of the art > in ZaphodHeads enablement?
Both Dave and Mario's patches are: Reviewed-by: Alex Deucher <alexander.deuc...@amd.com> > > thanks, > -mario > > > On 07/27/2015 01:43 AM, Dave Airlie wrote: >> >> From: Dave Airlie <airl...@redhat.com> >> >> 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. >> >> v2: fixup vblank fd registring. >> >> Signed-off-by: Dave Airlie <airl...@redhat.com> >> --- >> hw/xfree86/drivers/modesetting/driver.c | 191 >> ++++++++++++++--------- >> hw/xfree86/drivers/modesetting/driver.h | 32 ++-- >> hw/xfree86/drivers/modesetting/drmmode_display.c | 47 +++++- >> hw/xfree86/drivers/modesetting/drmmode_display.h | 5 + >> hw/xfree86/drivers/modesetting/vblank.c | 23 ++- >> 5 files changed, 209 insertions(+), 89 deletions(-) >> >> diff --git a/hw/xfree86/drivers/modesetting/driver.c >> b/hw/xfree86/drivers/modesetting/driver.c >> index 324b8bd..5dcc6a0 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) >> { >> @@ -366,6 +368,7 @@ ms_platform_probe(DriverPtr driver, >> intptr_t match_data) >> { >> ScrnInfoPtr scrn = NULL; >> + EntityInfoPtr pEnt; >> const char *path = xf86_platform_device_odev_attributes(dev)->path; >> int scr_flags = 0; >> >> @@ -374,12 +377,39 @@ 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"); >> + >> + pEnt = xf86GetEntityInfo(entity_num); >> + { >> + DevUnion *pPriv; >> + modesettingEntPtr pMSEnt; >> + >> + xf86SetEntitySharable(entity_num); >> + >> + if (ms_entity_index == -1) >> + ms_entity_index = xf86AllocateEntityPrivateIndex(); >> + >> + 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); >> @@ -658,61 +694,26 @@ try_enable_glamor(ScrnInfoPtr pScrn) >> #define DRM_CAP_CURSOR_HEIGHT 0x9 >> #endif >> >> -static Bool >> -PreInit(ScrnInfoPtr pScrn, int flags) >> +static Bool 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; >> + ms_ent = ms_ent_priv(pScrn); >> >> - pScrn->displayWidth = 640; /* default it */ >> + pEnt = ms->pEnt; >> >> - /* 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; >> - >> - 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 +750,62 @@ 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); >> >> diff --git a/hw/xfree86/drivers/modesetting/driver.h >> b/hw/xfree86/drivers/modesetting/driver.h >> index 9ae4966..1166165 100644 >> --- a/hw/xfree86/drivers/modesetting/driver.h >> +++ b/hw/xfree86/drivers/modesetting/driver.h >> @@ -44,12 +44,26 @@ >> #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; >> +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 +88,6 @@ struct ms_drm_queue { >> typedef struct _modesettingRec { >> int fd; >> >> - EntPtr entityPrivate; >> - >> int Chipset; >> EntityInfoPtr pEnt; >> #if XSERVER_LIBPCIACCESS >> @@ -88,9 +100,6 @@ typedef struct _modesettingRec { >> Bool noAccel; >> CloseScreenProcPtr CloseScreen; >> >> - /* Broken-out options. */ >> - OptionInfoPtr Options; >> - >> unsigned int SaveGeneration; >> >> CreateScreenResourcesProcPtr createScreenResources; >> @@ -114,6 +123,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 6a13660..ad9c062 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) >> { >> @@ -1357,7 +1390,7 @@ 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) >> @@ -1408,6 +1441,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; >> diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.h >> b/hw/xfree86/drivers/modesetting/drmmode_display.h >> index fe363c5..fca68a6 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/vblank.c >> b/hw/xfree86/drivers/modesetting/vblank.c >> index 0b7bf9d..77e0848 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); >> + } >> } >> > _______________________________________________ > xorg-devel@lists.x.org: X.Org development > Archives: http://lists.x.org/archives/xorg-devel > Info: http://lists.x.org/mailman/listinfo/xorg-devel _______________________________________________ xorg-devel@lists.x.org: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel