[PATCH] Allow/Fix use of multiple ZaphodHead outputs per x-screen.

Mario Kleiner mario.kleiner.de at gmail.com
Wed Jul 15 00:54:59 PDT 2015


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.

(Ported from radeon commit afab7839fc15722dbaa7203d00fe7f6ce5336b9d)

Signed-off-by: Mario Kleiner <mario.kleiner.de at gmail.com>
Cc: Michel Dänzer <michel.daenzer at amd.com>
---
 src/amdgpu_kms.c      |  4 ++++
 src/amdgpu_probe.h    |  1 +
 src/drmmode_display.c | 44 ++++++++++++++++++++++++++++++++------------
 3 files changed, 37 insertions(+), 12 deletions(-)

diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c
index 2019155..fb60310 100644
--- a/src/amdgpu_kms.c
+++ b/src/amdgpu_kms.c
@@ -924,10 +924,14 @@ static Bool AMDGPUCloseScreen_KMS(CLOSE_SCREEN_ARGS_DECL)
 {
 	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
 	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
+	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn);
 
 	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
 		       "AMDGPUCloseScreen\n");
 
+	/* Clear mask of assigned crtc's in this generation */
+	pAMDGPUEnt->assigned_crtcs = 0;
+
 	drmmode_uevent_fini(pScrn, &info->drmmode);
 	amdgpu_drm_queue_close(pScrn);
 
diff --git a/src/amdgpu_probe.h b/src/amdgpu_probe.h
index 1f760ac..4af7f48 100644
--- a/src/amdgpu_probe.h
+++ b/src/amdgpu_probe.h
@@ -80,6 +80,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;
 } AMDGPUEntRec, *AMDGPUEntPtr;
 
 extern const OptionInfoRec *AMDGPUOptionsWeak(void);
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index bce6774..8c2df13 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -846,14 +846,15 @@ void drmmode_crtc_hw_id(xf86CrtcPtr crtc)
 		drmmode_crtc->hw_id = -1;
 }
 
-static void drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
+static unsigned int drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
 {
 	xf86CrtcPtr crtc;
 	drmmode_crtc_private_ptr drmmode_crtc;
+	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(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 =
@@ -862,7 +863,12 @@ static void drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
 	crtc->driver_private = drmmode_crtc;
 	drmmode_crtc_hw_id(crtc);
 
-	return;
+	/* Mark num'th crtc as in use on this device. */
+	pAMDGPUEnt->assigned_crtcs |= (1 << num);
+	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
+		       "Allocated crtc nr. %d to this screen.\n", num);
+
+	return 1;
 }
 
 static xf86OutputStatus drmmode_output_detect(xf86OutputPtr output)
@@ -1222,7 +1228,7 @@ const char *output_names[] = { "None",
 
 #define NUM_OUTPUT_NAMES (sizeof(output_names) / sizeof(output_names[0]))
 
-static void
+static unsigned int
 drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
 {
 	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
@@ -1239,7 +1245,7 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
 	    drmModeGetConnector(drmmode->fd,
 				drmmode->mode_res->connectors[num]);
 	if (!koutput)
-		return;
+		return 0;
 
 	kencoders = calloc(sizeof(drmModeEncoderPtr), koutput->count_encoders);
 	if (!kencoders) {
@@ -1325,7 +1331,7 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
 		}
 	}
 
-	return;
+	return 1;
 out_free_encoders:
 	if (kencoders) {
 		for (i = 0; i < koutput->count_encoders; i++)
@@ -1333,7 +1339,7 @@ out_free_encoders:
 		free(kencoders);
 	}
 	drmModeFreeConnector(koutput);
-
+	return 0;
 }
 
 uint32_t find_clones(ScrnInfoPtr scrn, xf86OutputPtr output)
@@ -1600,7 +1606,9 @@ static void drm_wakeup_handler(pointer data, int err, pointer p)
 
 Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp)
 {
+	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn);
 	int i;
+	unsigned int crtcs_needed = 0;
 
 	xf86CrtcConfigInit(pScrn, &drmmode_xf86crtc_config_funcs);
 
@@ -1612,13 +1620,25 @@ Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp)
 
 	xf86CrtcSetSizeRange(pScrn, 320, 200, drmmode->mode_res->max_width,
 			     drmmode->mode_res->max_height);
-	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);
 
+	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
+		       "Initializing outputs ...\n");
 	for (i = 0; i < drmmode->mode_res->count_connectors; i++)
-		drmmode_output_init(pScrn, drmmode, i);
+		crtcs_needed += drmmode_output_init(pScrn, drmmode, i);
+
+	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
+		       "%d crtcs needed for screen.\n", crtcs_needed);
+
+	for (i = 0; i < drmmode->mode_res->count_crtcs; i++)
+		if (!xf86IsEntityShared(pScrn->entityList[0]) ||
+		    (crtcs_needed && !(pAMDGPUEnt->assigned_crtcs & (1 << i))))
+			crtcs_needed -= drmmode_crtc_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. Some outputs will stay off.\n",
+			   crtcs_needed);
 
 	/* workout clones */
 	drmmode_clones_init(pScrn, drmmode);
-- 
1.9.1



More information about the xorg-driver-ati mailing list