From: Dave Airlie <[email protected]> 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 <[email protected]> --- 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); + } } -- 2.4.3 _______________________________________________ [email protected]: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel
