[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