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

Mario Kleiner mario.kleiner.de at gmail.com
Tue Aug 4 15:08:37 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)

Tested on a triple display AMD setup with different combos
of one, two or three ZaphodHeads per one, two or three
x-screens. Also tested on nouveau and intel dual-display
setups with one or two x-screens.

Signed-off-by: Mario Kleiner <mario.kleiner.de at gmail.com>
---
 hw/xfree86/drivers/modesetting/driver.c          |  4 +++
 hw/xfree86/drivers/modesetting/driver.h          |  1 +
 hw/xfree86/drivers/modesetting/drmmode_display.c | 43 ++++++++++++++++++------
 3 files changed, 37 insertions(+), 11 deletions(-)

diff --git a/hw/xfree86/drivers/modesetting/driver.c b/hw/xfree86/drivers/modesetting/driver.c
index 5dcc6a0..fd41ccd 100644
--- a/hw/xfree86/drivers/modesetting/driver.c
+++ b/hw/xfree86/drivers/modesetting/driver.c
@@ -1328,6 +1328,10 @@ CloseScreen(ScreenPtr pScreen)
 {
     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
     modesettingPtr ms = modesettingPTR(pScrn);
+    modesettingEntPtr ms_ent = ms_ent_priv(pScrn);
+
+    /* Clear mask of assigned crtc's in this generation */
+    ms_ent->assigned_crtcs = 0;
 
 #ifdef GLAMOR
     if (ms->drmmode.glamor) {
diff --git a/hw/xfree86/drivers/modesetting/driver.h b/hw/xfree86/drivers/modesetting/driver.h
index 1166165..14137c1 100644
--- a/hw/xfree86/drivers/modesetting/driver.h
+++ b/hw/xfree86/drivers/modesetting/driver.h
@@ -43,6 +43,7 @@
 
 #include "drmmode_display.h"
 #define DRV_ERROR(msg)	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, msg);
+#define MS_LOGLEVEL_DEBUG 4
 
 typedef enum {
     OPTION_SW_CURSOR,
diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c b/hw/xfree86/drivers/modesetting/drmmode_display.c
index ad9c062..60c35be 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.c
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.c
@@ -821,15 +821,16 @@ drmmode_crtc_vblank_pipe(int crtc_id)
         return 0;
 }
 
-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;
+    modesettingEntPtr ms_ent = ms_ent_priv(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 =
@@ -837,6 +838,13 @@ drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res
     drmmode_crtc->drmmode = drmmode;
     drmmode_crtc->vblank_pipe = drmmode_crtc_vblank_pipe(num);
     crtc->driver_private = drmmode_crtc;
+
+    /* Mark num'th crtc as in use on this device. */
+    ms_ent->assigned_crtcs |= (1 << num);
+    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, MS_LOGLEVEL_DEBUG,
+                   "Allocated crtc nr. %d to this screen.\n", num);
+
+    return 1;
 }
 
 static xf86OutputStatus
@@ -1378,7 +1386,7 @@ drmmode_create_name(ScrnInfoPtr pScrn, drmModeConnectorPtr koutput, char *name,
         snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], koutput->connector_type_id - 1);
 }
 
-static void
+static unsigned int
 drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res, int num, Bool dynamic)
 {
     xf86OutputPtr output;
@@ -1394,7 +1402,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]);
@@ -1425,7 +1433,7 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r
             drmmode_output = output->driver_private;
             drmmode_output->output_id = mode_res->connectors[num];
             drmmode_output->mode_output = koutput;
-            return;
+            return 1;
         }
     }
 
@@ -1497,7 +1505,8 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r
 
     if (dynamic)
         output->randr_output = RROutputCreate(xf86ScrnToScreen(pScrn), output->name, strlen(output->name), output);
-    return;
+    return 1;
+
  out_free_encoders:
     if (kencoders) {
         for (i = 0; i < koutput->count_encoders; i++)
@@ -1506,6 +1515,7 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r
     }
     drmModeFreeConnector(koutput);
 
+    return 0;
 }
 
 static uint32_t
@@ -1727,9 +1737,11 @@ static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = {
 Bool
 drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp)
 {
+    modesettingEntPtr ms_ent = ms_ent_priv(pScrn);
     int i;
     int ret;
     uint64_t value = 0;
+    unsigned int crtcs_needed = 0;
     drmModeResPtr mode_res;
 
     /* check for dumb capability */
@@ -1748,15 +1760,24 @@ drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp)
     if (!mode_res)
         return FALSE;
 
+    for (i = 0; i < mode_res->count_connectors; i++)
+        crtcs_needed += drmmode_output_init(pScrn, drmmode, mode_res, i, FALSE);
+
+    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, MS_LOGLEVEL_DEBUG,
+                   "Up to %d crtcs needed for screen.\n", crtcs_needed);
+
     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, FALSE);
+            (crtcs_needed && !(ms_ent->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);
-- 
2.1.4



More information about the xorg-devel mailing list