diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2010-10-25 10:37:08 +1000 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2010-10-25 10:46:53 +1000 |
commit | 9737a812aacbc544b93eeaa031cf1c2e8adbd661 (patch) | |
tree | 1b1b66bbd4509f6ad5f78187e3c9ab6bcd26e1ca | |
parent | d40c16f5497739c0215f37566db1651a74cb20ba (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.man | 10 | ||||
-rw-r--r-- | src/drmmode_display.c | 66 | ||||
-rw-r--r-- | src/nv_const.h | 2 | ||||
-rw-r--r-- | src/nv_driver.c | 19 | ||||
-rw-r--r-- | src/nv_type.h | 1 |
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; |