diff options
author | Mario Kleiner <mario.kleiner.de@gmail.com> | 2014-06-23 11:25:41 +0200 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2014-08-11 08:38:46 +1000 |
commit | 6e71bdf5a9da15c60694fa8543243e37a32c5faf (patch) | |
tree | 65e31fb42ee25c3692882c15a66a23290853a1e3 | |
parent | fcf91a275e96f14e49a93dc3f8dd6798cf7d98f3 (diff) |
Allow/Fix use of multiple ZaphodHead outputs per x-screen.
Defining multiple ZaphodHead outputs per x-screen in a
multiple x-screen's per gpu configuration caused all
outputs except one per x-screen to go dark, because
there was a fixed mapping x-screen number -> crtc number,
limiting the number of crtc's per x-screen to one.
On a ZaphodHead's setup, be more clever and assign
as many crtc's to a given x-screen as there are
ZaphodHeads defined for that screen, assuming
there are enough unused crtc's available.
Tested on a triple display setup with different combos
of one, two or three ZaphodHeads per one, two or three
x-screens.
Signed-off-by: Mario Kleiner <mario.kleiner.de@gmail.com>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r-- | src/drmmode_display.c | 50 | ||||
-rw-r--r-- | src/nv_driver.c | 1 | ||||
-rw-r--r-- | src/nv_type.h | 1 |
3 files changed, 37 insertions, 15 deletions
diff --git a/src/drmmode_display.c b/src/drmmode_display.c index 501440a..dc15221 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -746,17 +746,18 @@ static const xf86CrtcFuncsRec drmmode_crtc_funcs = { }; -static void +static unsigned int drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num) { NVPtr pNv = NVPTR(pScrn); + NVEntPtr pNVEnt = NVEntPriv(pScrn); xf86CrtcPtr crtc; drmmode_crtc_private_ptr drmmode_crtc; int ret; crtc = xf86CrtcCreate(pScrn, &drmmode_crtc_funcs); if (crtc == NULL) - return; + return 0; drmmode_crtc = xnfcalloc(sizeof(drmmode_crtc_private_rec), 1); drmmode_crtc->mode_crtc = drmModeGetCrtc(drmmode->fd, @@ -770,7 +771,12 @@ drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num) crtc->driver_private = drmmode_crtc; - return; + /* Mark num'th crtc as in use on this device. */ + pNVEnt->assigned_crtcs |= (1 << num); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Allocated crtc nr. %d to this screen.\n", num); + + return 1; } static xf86OutputStatus @@ -1197,7 +1203,7 @@ drmmode_zaphod_match(ScrnInfoPtr pScrn, const char *s, char *output_name) return FALSE; } -static void +static unsigned int drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num) { NVPtr pNv = NVPTR(pScrn); @@ -1211,12 +1217,12 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num) koutput = drmModeGetConnector(drmmode->fd, drmmode->mode_res->connectors[num]); if (!koutput) - return; + return 0; kencoder = drmModeGetEncoder(drmmode->fd, koutput->encoders[0]); if (!kencoder) { drmModeFreeConnector(koutput); - return; + return 0; } if (koutput->connector_type >= NUM_OUTPUT_NAMES) @@ -1239,18 +1245,18 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num) if (!drmmode_zaphod_match(pScrn, s, name)) { drmModeFreeEncoder(kencoder); drmModeFreeConnector(koutput); - return; + return 0; } } else { if (pNv->Primary && (num != 0)) { drmModeFreeEncoder(kencoder); drmModeFreeConnector(koutput); - return; + return 0; } else if (pNv->Secondary && (num != 1)) { drmModeFreeEncoder(kencoder); drmModeFreeConnector(koutput); - return; + return 0; } } } @@ -1259,7 +1265,7 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num) if (!output) { drmModeFreeEncoder(kencoder); drmModeFreeConnector(koutput); - return; + return 0; } drmmode_output = calloc(sizeof(drmmode_output_private_rec), 1); @@ -1267,7 +1273,7 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num) xf86OutputDestroy(output); drmModeFreeConnector(koutput); drmModeFreeEncoder(kencoder); - return; + return 0; } drmmode_output->output_id = drmmode->mode_res->connectors[num]; @@ -1285,6 +1291,8 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num) output->interlaceAllowed = true; output->doubleScanAllowed = true; + + return 1; } static Bool @@ -1400,7 +1408,9 @@ static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = { Bool drmmode_pre_init(ScrnInfoPtr pScrn, int fd, int cpp) { drmmode_ptr drmmode; + NVEntPtr pNVEnt = NVEntPriv(pScrn); int i; + unsigned int crtcs_needed = 0; drmmode = xnfalloc(sizeof *drmmode); drmmode->fd = fd; @@ -1423,14 +1433,24 @@ Bool drmmode_pre_init(ScrnInfoPtr pScrn, int fd, int cpp) goto done; } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Initializing outputs ...\n"); + for (i = 0; i < drmmode->mode_res->count_connectors; i++) + crtcs_needed += drmmode_output_init(pScrn, drmmode, i); + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "%d crtcs needed for screen.\n", crtcs_needed); + 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); + (crtcs_needed && !(pNVEnt->assigned_crtcs & (1 << i)))) + crtcs_needed -= drmmode_crtc_init(pScrn, drmmode, i); } - for (i = 0; i < drmmode->mode_res->count_connectors; i++) - drmmode_output_init(pScrn, drmmode, i); + /* All ZaphodHeads outputs provided with matching crtcs? */ + if (xf86IsEntityShared(pScrn->entityList[0]) && (crtcs_needed > 0)) + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "%d ZaphodHeads crtcs unavailable. Trouble!\n", + crtcs_needed); done: #ifdef NOUVEAU_PIXMAP_SHARING diff --git a/src/nv_driver.c b/src/nv_driver.c index 2fa3802..a9524a0 100644 --- a/src/nv_driver.c +++ b/src/nv_driver.c @@ -276,6 +276,7 @@ NVInitScrn(ScrnInfoPtr pScrn, struct xf86_platform_device *platform_dev, pPriv->ptr = xnfcalloc(sizeof(NVEntRec), 1); pNVEnt = pPriv->ptr; pNVEnt->platform_dev = platform_dev; + pNVEnt->assigned_crtcs = 0; } xf86SetEntityInstanceForScreen(pScrn, entity_num, diff --git a/src/nv_type.h b/src/nv_type.h index b4889bf..0f4b0bc 100644 --- a/src/nv_type.h +++ b/src/nv_type.h @@ -32,6 +32,7 @@ typedef struct _NVRec *NVPtr; typedef struct { int fd; struct xf86_platform_device *platform_dev; + unsigned int assigned_crtcs; } NVEntRec, *NVEntPtr; NVEntPtr NVEntPriv(ScrnInfoPtr pScrn); |