summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2010-10-25 10:37:08 +1000
committerBen Skeggs <bskeggs@redhat.com>2010-10-25 10:46:53 +1000
commit9737a812aacbc544b93eeaa031cf1c2e8adbd661 (patch)
tree1b1b66bbd4509f6ad5f78187e3c9ab6bcd26e1ca
parentd40c16f5497739c0215f37566db1651a74cb20ba (diff)
kms: initial pass at supporting zaphod-mode
This works ok from some simple testing, there's undoubtedly things that will need polishing still however. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--man/nouveau.man10
-rw-r--r--src/drmmode_display.c66
-rw-r--r--src/nv_const.h2
-rw-r--r--src/nv_driver.c19
-rw-r--r--src/nv_type.h1
5 files changed, 92 insertions, 6 deletions
diff --git a/man/nouveau.man b/man/nouveau.man
index a8961ad..39de690 100644
--- a/man/nouveau.man
+++ b/man/nouveau.man
@@ -77,12 +77,22 @@ Enable or disable use of the shadow framebuffer layer. Default: off.
Enable or disable wfb, only affects nv50+. Useful for some legacy configurations where high rendering latency is perceived. Default: wfb is disabled.
.TP
.BI "Option \*qGLXVBlank\*q \*q" boolean \*q
Synchronize GLX clients to VBlank. Useful where tearing is a problem,
harmful if the GPU isn't fast enough to keep up with the monitor
refresh rate. Default: off.
+.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 most 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.
.SH "SEE ALSO"
__xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__)
.SH AUTHORS
Authors include: David McKay, Jarno Paananen, Chas Inman, Dave Schmenk,
Mark Vojkovich
.SH COPYRIGHT
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 94b19ea..c5b57eb 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -942,19 +942,54 @@ const char *output_names[] = { "None",
"HDMI",
"TV",
"eDP",
};
#define NUM_OUTPUT_NAMES (sizeof(output_names) / sizeof(output_names[0]))
+static Bool
+drmmode_zaphod_match(ScrnInfoPtr pScrn, 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;
+}
+
static void
drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
{
+ NVPtr pNv = NVPTR(pScrn);
xf86OutputPtr output;
drmModeConnectorPtr koutput;
drmModeEncoderPtr kencoder;
drmmode_output_private_ptr drmmode_output;
+ const char *s;
char name[32];
koutput = drmModeGetConnector(drmmode->fd,
drmmode->mode_res->connectors[num]);
if (!koutput)
return;
@@ -970,12 +1005,34 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
koutput->connector_type_id);
else
snprintf(name, 32, "%s-%d",
output_names[koutput->connector_type],
koutput->connector_type_id);
+ if (xf86IsEntityShared(pScrn->entityList[0])) {
+ s = xf86GetOptValString(pNv->Options, OPTION_ZAPHOD_HEADS);
+ if (s) {
+ if (!drmmode_zaphod_match(pScrn, s, name)) {
+ drmModeFreeEncoder(kencoder);
+ drmModeFreeConnector(koutput);
+ return;
+ }
+ } else {
+ if (pNv->Primary && (num != 0)) {
+ drmModeFreeEncoder(kencoder);
+ drmModeFreeConnector(koutput);
+ return;
+ } else
+ if (pNv->Secondary && (num != 1)) {
+ drmModeFreeEncoder(kencoder);
+ drmModeFreeConnector(koutput);
+ return;
+ }
+ }
+ }
+
output = xf86OutputCreate (pScrn, &drmmode_output_funcs, name);
if (!output) {
drmModeFreeEncoder(kencoder);
drmModeFreeConnector(koutput);
return;
}
@@ -1000,14 +1057,12 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
output->possible_crtcs = kencoder->possible_crtcs;
output->possible_clones = kencoder->possible_clones;
output->interlaceAllowed = true;
output->doubleScanAllowed = true;
-
- return;
}
static Bool
drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height)
{
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
@@ -1118,14 +1173,17 @@ Bool drmmode_pre_init(ScrnInfoPtr pScrn, int fd, int cpp)
drmmode->mode_res = drmModeGetResources(drmmode->fd);
if (!drmmode->mode_res)
return FALSE;
xf86CrtcSetSizeRange(pScrn, 320, 200, drmmode->mode_res->max_width,
drmmode->mode_res->max_height);
- for (i = 0; i < drmmode->mode_res->count_crtcs; i++)
- drmmode_crtc_init(pScrn, drmmode, i);
+ for (i = 0; i < drmmode->mode_res->count_crtcs; i++) {
+ if (!xf86IsEntityShared(pScrn->entityList[0] ||
+ pScrn->confScreen->device->screen == i))
+ drmmode_crtc_init(pScrn, drmmode, i);
+ }
for (i = 0; i < drmmode->mode_res->count_connectors; i++)
drmmode_output_init(pScrn, drmmode, i);
xf86InitialConfiguration(pScrn, TRUE);
diff --git a/src/nv_const.h b/src/nv_const.h
index c355cad..f80d125 100644
--- a/src/nv_const.h
+++ b/src/nv_const.h
@@ -12,22 +12,24 @@ typedef enum {
OPTION_HW_CURSOR,
OPTION_NOACCEL,
OPTION_SHADOW_FB,
OPTION_VIDEO_KEY,
OPTION_WFB,
OPTION_GLX_VBLANK,
+ OPTION_ZAPHOD_HEADS,
} NVOpts;
static const OptionInfoRec NVOptions[] = {
{ OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_VIDEO_KEY, "VideoKey", OPTV_INTEGER, {0}, FALSE },
{ OPTION_WFB, "WrappedFB", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_GLX_VBLANK, "GLXVBlank", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_ZAPHOD_HEADS, "ZaphodHeads", OPTV_STRING, {0}, FALSE },
{ -1, NULL, OPTV_NONE, {0}, FALSE }
};
#endif /* __NV_CONST_H__ */
diff --git a/src/nv_driver.c b/src/nv_driver.c
index fad7d6a..f351fac 100644
--- a/src/nv_driver.c
+++ b/src/nv_driver.c
@@ -202,12 +202,13 @@ NVPciProbe(DriverPtr drv, int entity_num, struct pci_device *pci_dev,
PciChipsets NVChipsets[] = {
{ pci_dev->device_id,
(pci_dev->vendor_id << 16) | pci_dev->device_id, NULL },
{ -1, -1, NULL }
};
struct nouveau_device *dev = NULL;
+ EntityInfoPtr pEnt = NULL;
ScrnInfoPtr pScrn = NULL;
drmVersion *version;
int chipset, ret;
char *busid;
if (!xf86LoaderCheckSymbol("DRICreatePCIBusID")) {
@@ -277,12 +278,18 @@ NVPciProbe(DriverPtr drv, int entity_num, struct pci_device *pci_dev,
pScrn->SwitchMode = NVSwitchMode;
pScrn->AdjustFrame = NVAdjustFrame;
pScrn->EnterVT = NVEnterVT;
pScrn->LeaveVT = NVLeaveVT;
pScrn->FreeScreen = NVFreeScreen;
+ xf86SetEntitySharable(entity_num);
+
+ pEnt = xf86GetEntityInfo(entity_num);
+ xf86SetEntityInstanceForScreen(pScrn, pEnt->index, xf86GetNumEntityInstances(pEnt->index) - 1);
+ free(pEnt);
+
return TRUE;
}
#define MAX_CHIPS MAXSCREENS
Bool
@@ -625,16 +632,24 @@ NVPreInit(ScrnInfoPtr pScrn, int flags)
pNv = NVPTR(pScrn);
/* Get the entity, and make sure it is PCI. */
pNv->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
if (pNv->pEnt->location.type != BUS_PCI)
return FALSE;
-
+
+ if (xf86IsEntityShared(pScrn->entityList[0])) {
+ if(!xf86IsPrimInitDone(pScrn->entityList[0])) {
+ pNv->Primary = TRUE;
+ xf86SetPrimInitDone(pScrn->entityList[0]);
+ } else {
+ pNv->Secondary = TRUE;
+ }
+ }
+
/* Find the PCI info for this screen */
pNv->PciInfo = xf86GetPciInfoForEntity(pNv->pEnt->index);
- pNv->Primary = xf86IsPrimaryPci(pNv->PciInfo);
/* Initialise the kernel module */
if (!NVPreInitDRM(pScrn))
NVPreInitFail("\n");
dev = pNv->dev;
diff --git a/src/nv_type.h b/src/nv_type.h
index 94c385a..4204556 100644
--- a/src/nv_type.h
+++ b/src/nv_type.h
@@ -30,12 +30,13 @@
typedef struct _NVRec *NVPtr;
typedef struct _NVRec {
uint32_t Architecture;
EntityInfoPtr pEnt;
struct pci_device *PciInfo;
Bool Primary;
+ Bool Secondary;
/* Various pinned memory regions */
struct nouveau_bo * scanout;
struct nouveau_bo * offscreen;
void * offscreen_map;
struct nouveau_bo * GART;