On some chipset we try to avoid possibly invasive output detection methods (like load detect which can cause flickering elsewhere) in the output poll work. Drivers could hence return unknown when a previous full ->detect call returned a different state. This change will generate a hotplug event, forcing userspace to do a full scan. This in turn updates the connector->status field so that we will _again_ get a state change when the hotplug work re-runs in 10 seconds. To avoid this ping-pong loop detect this situation and clamp the connector state to the old value. Patch is inspired by a patch from Knut Peterson. Knut's patch completely ignored connector state changes if either the old or new status was unknown, which seemed to be a bit too agressive to me. References: http://lists.freedesktop.org/archives/dri-devel/2012-August/025975.html Cc: Knut Petersen <Knut_Petersen at t-online.de> Cc: Alex Deucher <alexander.deucher at amd.com> Signed-off-by: Daniel Vetter <daniel.vetter at ffwll.ch> --- drivers/gpu/drm/drm_crtc_helper.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 1c0c0bc..9985a17 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -1040,6 +1040,24 @@ static void output_poll_execute(struct work_struct *work) if (old_status != connector->status) { const char *old, *new; + /* + * The poll work sets force=false when calling detect so + * that drivers can avoid to do disruptive tests (e.g. + * when load detect cycles could cause flickering on + * other, running displays). This bears the risk that we + * flip-flop between unknown here in the poll work and + * the real state when userspace forces a full detect + * call after receiving a hotplug event due to this + * change. + * + * Hence clamp an unknown detect status to the old + * value. + */ + if (connector->status == connector_status_unknown) { + connector->status = old_status; + continue; + } + old = drm_get_connector_status_name(old_status); new = drm_get_connector_status_name(connector->status); -- 1.7.11.7