[PATCH] [RFC] modesetting: add zaphod support (v2)
Alex Deucher
alexdeucher at gmail.com
Thu Aug 6 08:04:41 PDT 2015
On Tue, Aug 4, 2015 at 6:18 PM, Mario Kleiner
<mario.kleiner.de at gmail.com> wrote:
> Hi Dave,
>
> thanks for implementing this!
>
> This one is
>
> Reviewed-and-tested-by: Mario Kleiner <mario.kleiner.de at 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.deucher at amd.com>
>
> thanks,
> -mario
>
>
> On 07/27/2015 01:43 AM, Dave Airlie wrote:
>>
>> From: Dave Airlie <airlied at 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 <airlied at 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 at lists.x.org: X.Org development
> Archives: http://lists.x.org/archives/xorg-devel
> Info: http://lists.x.org/mailman/listinfo/xorg-devel
More information about the xorg-devel
mailing list