modesetting: re-set the crtc's mode when link-status goes BAD

Despite all the careful planning of the kernel, a link may become
insufficient to handle the currently-set mode. At this point, the
kernel should mark this particular configuration as being broken
and potentially prune the mode before setting the offending connector's
link-status to BAD and send the userspace a hotplug event. This may
happen right after a modeset or later on.

Upon receiving a hot-plug event, we iterate through the connectors to
re-apply the currently-set mode on all the connectors that have a
link-status property set to BAD. The kernel may be able to get the
link to work by dropping to using a lower link bpp (with the same
display bpp). However, the modeset may fail if the kernel has pruned
the mode, so to make users aware of this problem a warning is outputed
in the logs to warn about having a potentially-black display.

This patch does not modify the current behaviour of always propagating
the events to the randr clients. This allows desktop environments to
re-probe the connectors and select a new resolution based on the new
(currated) mode list if a mode disapeared. This behaviour is expected in
order to pass the Display Port compliance tests.

(Ported from xserver commit bcee1b76aa0db8525b491485e90b8740763d7de6)

[ Michel: Bump libdrm dependency to >= 2.4.78 for
  DRM_MODE_LINK_STATUS_BAD ]
(Ported from radeon commit 0472a605e0ec8fec1892bbc3a84698b7ef9c5296)
Acked-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
Martin Peres
2017-08-22 18:43:24 +09:00
committed by Michel Dänzer
parent a2ee5c36c7
commit 0de05767ad
2 changed files with 44 additions and 1 deletions

View File

@@ -70,7 +70,7 @@ XORG_DRIVER_CHECK_EXT(XV, videoproto)
XORG_DRIVER_CHECK_EXT(DPMSExtension, xextproto)
# Checks for libraries.
PKG_CHECK_MODULES(LIBDRM, [libdrm >= 2.4.72])
PKG_CHECK_MODULES(LIBDRM, [libdrm >= 2.4.78])
PKG_CHECK_MODULES(LIBDRM_AMDGPU, [libdrm_amdgpu >= 2.4.72])
PKG_CHECK_MODULES(GBM, [gbm])

View File

@@ -2627,6 +2627,49 @@ amdgpu_mode_hotplug(ScrnInfoPtr scrn, drmmode_ptr drmmode)
Bool changed = FALSE;
int num_dvi = 0, num_hdmi = 0;
/* Try to re-set the mode on all the connectors with a BAD link-state:
* This may happen if a link degrades and a new modeset is necessary, using
* different link-training parameters. If the kernel found that the current
* mode is not achievable anymore, it should have pruned the mode before
* sending the hotplug event. Try to re-set the currently-set mode to keep
* the display alive, this will fail if the mode has been pruned.
* In any case, we will send randr events for the Desktop Environment to
* deal with it, if it wants to.
*/
for (i = 0; i < config->num_output; i++) {
xf86OutputPtr output = config->output[i];
drmmode_output_private_ptr drmmode_output = output->driver_private;
uint32_t con_id = drmmode_output->mode_output->connector_id;
drmModeConnectorPtr koutput;
/* Get an updated view of the properties for the current connector and
* look for the link-status property
*/
koutput = drmModeGetConnectorCurrent(pAMDGPUEnt->fd, con_id);
for (j = 0; koutput && j < koutput->count_props; j++) {
drmModePropertyPtr props;
props = drmModeGetProperty(pAMDGPUEnt->fd, koutput->props[j]);
if (props && props->flags & DRM_MODE_PROP_ENUM &&
!strcmp(props->name, "link-status") &&
koutput->prop_values[j] == DRM_MODE_LINK_STATUS_BAD) {
xf86CrtcPtr crtc = output->crtc;
if (!crtc)
continue;
/* the connector got a link failure, re-set the current mode */
drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation,
crtc->x, crtc->y);
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"hotplug event: connector %u's link-state is BAD, "
"tried resetting the current mode. You may be left "
"with a black screen if this fails...\n", con_id);
}
drmModeFreeProperty(props);
}
drmModeFreeConnector(koutput);
}
mode_res = drmModeGetResources(pAMDGPUEnt->fd);
if (!mode_res)
goto out;