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. Signed-off-by: Martin Peres <martin.peres@linux.intel.com> Reviewed-by: Eric Anholt <eric@anholt.net>
This commit is contained in:
parent
ea91996a9c
commit
bcee1b76aa
|
@ -2253,6 +2253,10 @@ drmmode_setup_colormap(ScreenPtr pScreen, ScrnInfoPtr pScrn)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_UDEV_KMS
|
||||
|
||||
#define DRM_MODE_LINK_STATUS_GOOD 0
|
||||
#define DRM_MODE_LINK_STATUS_BAD 1
|
||||
|
||||
static void
|
||||
drmmode_handle_uevents(int fd, void *closure)
|
||||
{
|
||||
|
@ -2272,6 +2276,49 @@ drmmode_handle_uevents(int fd, void *closure)
|
|||
if (!found)
|
||||
return;
|
||||
|
||||
/* 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(drmmode->fd, con_id);
|
||||
for (j = 0; koutput && j < koutput->count_props; j++) {
|
||||
drmModePropertyPtr props;
|
||||
props = drmModeGetProperty(drmmode->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(drmmode->fd);
|
||||
if (!mode_res)
|
||||
goto out;
|
||||
|
@ -2336,6 +2383,10 @@ out_free_res:
|
|||
out:
|
||||
RRGetInfo(xf86ScrnToScreen(scrn), TRUE);
|
||||
}
|
||||
|
||||
#undef DRM_MODE_LINK_STATUS_BAD
|
||||
#undef DRM_MODE_LINK_STATUS_GOOD
|
||||
|
||||
#endif
|
||||
|
||||
void
|
||||
|
|
Loading…
Reference in New Issue