From afab7839fc15722dbaa7203d00fe7f6ce5336b9d Mon Sep 17 00:00:00 2001 From: Mario Kleiner Date: Wed, 10 Jun 2015 20:55:08 +0200 Subject: Allow/Fix use of multiple ZaphodHead outputs per x-screen. (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. This is a port of similar code from xf86-video-nouveau. v2: Implement suggestions by Michel Dänzer: Less verbose debug output, more clear warning message on crtc allocation failure. Move clearing of per gpu assigned_crtc mask to CloseScreen, indeed testing shows no need for the more complex new server generation check from v1. Signed-off-by: Mario Kleiner (v1) Reviewed-by: Alex Deucher Reviewed-by: Michel Dänzer --- src/drmmode_display.c | 46 +++++++++++++++++++++++++++++++++------------- src/radeon_kms.c | 4 ++++ src/radeon_probe.h | 1 + 3 files changed, 38 insertions(+), 13 deletions(-) diff --git a/src/drmmode_display.c b/src/drmmode_display.c index c12bf513..35648533 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -1012,15 +1012,16 @@ void drmmode_crtc_hw_id(xf86CrtcPtr crtc) drmmode_crtc->hw_id = tmp; } -static void +static unsigned int drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res, int num) { xf86CrtcPtr crtc; drmmode_crtc_private_ptr drmmode_crtc; + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); 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, mode_res->crtcs[num]); @@ -1028,7 +1029,12 @@ drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res crtc->driver_private = drmmode_crtc; drmmode_crtc_hw_id(crtc); - return; + /* Mark num'th crtc as in use on this device. */ + pRADEONEnt->assigned_crtcs |= (1 << num); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Allocated crtc nr. %d to this screen.\n", num); + + return 1; } static xf86OutputStatus @@ -1461,7 +1467,7 @@ drmmode_create_name(ScrnInfoPtr pScrn, drmModeConnectorPtr koutput, char *name, } } -static void +static unsigned int drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res, int num, int *num_dvi, int *num_hdmi, int dynamic) { xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); @@ -1478,7 +1484,7 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r koutput = drmModeGetConnector(drmmode->fd, mode_res->connectors[num]); if (!koutput) - return; + return 0; for (i = 0; i < koutput->count_props; i++) { props = drmModeGetProperty(drmmode->fd, koutput->props[i]); @@ -1524,7 +1530,7 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r for (i = 0; i < koutput->count_encoders; i++) drmModeFreeEncoder(kencoders[i]); free(kencoders); - return; + return 0; } } @@ -1587,7 +1593,7 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r drmmode_output_create_resources(output); } - return; + return 1; out_free_encoders: if (kencoders){ for (i = 0; i < koutput->count_encoders; i++) @@ -1595,7 +1601,7 @@ out_free_encoders: free(kencoders); } drmModeFreeConnector(koutput); - + return 0; } uint32_t find_clones(ScrnInfoPtr scrn, xf86OutputPtr output) @@ -2030,8 +2036,10 @@ drm_wakeup_handler(pointer data, int err, pointer p) Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp) { + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); int i, num_dvi = 0, num_hdmi = 0; drmModeResPtr mode_res; + unsigned int crtcs_needed = 0; xf86CrtcConfigInit(pScrn, &drmmode_xf86crtc_config_funcs); @@ -2041,14 +2049,26 @@ Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp) if (!mode_res) return FALSE; + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Initializing outputs ...\n"); + for (i = 0; i < mode_res->count_connectors; i++) + crtcs_needed += drmmode_output_init(pScrn, drmmode, mode_res, + i, &num_dvi, &num_hdmi, 0); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "%d crtcs needed for screen.\n", crtcs_needed); + drmmode->count_crtcs = mode_res->count_crtcs; xf86CrtcSetSizeRange(pScrn, 320, 200, mode_res->max_width, mode_res->max_height); for (i = 0; i < mode_res->count_crtcs; i++) - if (!xf86IsEntityShared(pScrn->entityList[0]) || pScrn->confScreen->device->screen == i) - drmmode_crtc_init(pScrn, drmmode, mode_res, i); - - for (i = 0; i < mode_res->count_connectors; i++) - drmmode_output_init(pScrn, drmmode, mode_res, i, &num_dvi, &num_hdmi, 0); + if (!xf86IsEntityShared(pScrn->entityList[0]) || + (crtcs_needed && !(pRADEONEnt->assigned_crtcs & (1 << i)))) + crtcs_needed -= drmmode_crtc_init(pScrn, drmmode, mode_res, 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. Some outputs will stay off.\n", + crtcs_needed); /* workout clones */ drmmode_clones_init(pScrn, drmmode, mode_res); diff --git a/src/radeon_kms.c b/src/radeon_kms.c index 0690ef06..25a746db 100644 --- a/src/radeon_kms.c +++ b/src/radeon_kms.c @@ -1457,10 +1457,14 @@ static Bool RADEONCloseScreen_KMS(CLOSE_SCREEN_ARGS_DECL) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, "RADEONCloseScreen\n"); + /* Clear mask of assigned crtc's in this generation */ + pRADEONEnt->assigned_crtcs = 0; + drmmode_uevent_fini(pScrn, &info->drmmode); radeon_drm_queue_close(pScrn); radeon_cs_flush_indirect(pScrn); diff --git a/src/radeon_probe.h b/src/radeon_probe.h index 3fe4644c..958cb23b 100644 --- a/src/radeon_probe.h +++ b/src/radeon_probe.h @@ -142,6 +142,7 @@ typedef struct 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 -- cgit v1.2.3