[PATCH] [RFC] modesetting: add zaphod support (v2)
Dave Airlie
airlied at gmail.com
Sun Jul 26 16:43:55 PDT 2015
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);
+ }
}
--
2.4.3
More information about the xorg-devel
mailing list