From patchwork Thu Jun 4 15:26:18 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Chris Wilson X-Patchwork-Id: 6547861 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 6A9919F3D1 for ; Thu, 4 Jun 2015 15:26:44 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 738B72076E for ; Thu, 4 Jun 2015 15:26:43 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 1E0F82076C for ; Thu, 4 Jun 2015 15:26:42 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 482696E1DA; Thu, 4 Jun 2015 08:26:41 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from fireflyinternet.com (mail.fireflyinternet.com [87.106.93.118]) by gabe.freedesktop.org (Postfix) with ESMTP id D03DF6E1DA for ; Thu, 4 Jun 2015 08:26:39 -0700 (PDT) X-Default-Received-SPF: pass (skip=forwardok (res=PASS)) x-ip-name=78.156.65.138; Received: from nuc-i3427.alporthouse.com (unverified [78.156.65.138]) by fireflyinternet.com (Firefly Internet (M1)) with ESMTP id 40710555-1500048 for multiple; Thu, 04 Jun 2015 16:27:11 +0100 From: Chris Wilson To: intel-gfx@lists.freedesktop.org Date: Thu, 4 Jun 2015 16:26:18 +0100 Message-Id: <1433431578-14373-1-git-send-email-chris@chris-wilson.co.uk> X-Mailer: git-send-email 1.9.1 X-Originating-IP: 78.156.65.138 X-Country: code=GB country="United Kingdom" ip=78.156.65.138 Subject: [Intel-gfx] [PATCH] drm/i915: Avoid fluctuating to UNKNOWN connector status during forced probes X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP For old-school component TV and CRT connectors, we require a heavyweight load-detection mechanism. This involves setting up a CRTC and sending a signal to the output, before reading back any response. As that is quite slow and CPU heavy, the process is only performed when the output detection is forced by user request. As it requires a driving CRTC, we often don't have the resources to complete the probe. This leaves us in a quandary where the unforced path just returns the old connector status, but the forced detection path elects to return UNKNOWN. If we have an active connection, we likely have the resources available to complete the probe - but if it is currently disconnected, then it becomes unknown and triggers a hotplug event, with often quite unfortunate userspace behaviour (e.g. one output is blanked and the spurious TV turned on). To reduce spurious hotplug events on older devices, we can prevent transitions between disconnected <-> unknown. References: https://bugs.freedesktop.org/show_bug.cgi?id=87049 Signed-off-by: Chris Wilson Reviewed-by: Ville Syrjälä Tested-By: Intel Graphics QA PRTS (Patch Regression Test System Contact: shuang.he@intel.com) --- drivers/gpu/drm/i915/intel_crt.c | 39 ++++++++++++++++++--------------------- drivers/gpu/drm/i915/intel_tv.c | 25 +++++++++---------------- 2 files changed, 27 insertions(+), 37 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 521af2c..70c5288 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -666,8 +666,6 @@ intel_crt_detect(struct drm_connector *connector, bool force) struct intel_encoder *intel_encoder = &crt->base; enum intel_display_power_domain power_domain; enum drm_connector_status status; - struct intel_load_detect_pipe tmp; - struct drm_modeset_acquire_ctx ctx; DRM_DEBUG_KMS("[CONNECTOR:%d:%s] force=%d\n", connector->base.id, connector->name, @@ -703,27 +701,26 @@ intel_crt_detect(struct drm_connector *connector, bool force) goto out; } - if (!force) { - status = connector->status; - goto out; - } - - drm_modeset_acquire_init(&ctx, 0); - - /* for pre-945g platforms use load detect */ - if (intel_get_load_detect_pipe(connector, NULL, &tmp, &ctx)) { - if (intel_crt_detect_ddc(connector)) - status = connector_status_connected; - else if (INTEL_INFO(dev)->gen < 4) - status = intel_crt_load_detect(crt); - else + status = connector->status; + if (force) { + struct intel_load_detect_pipe tmp; + struct drm_modeset_acquire_ctx ctx; + + drm_modeset_acquire_init(&ctx, 0); + + /* for pre-945g platforms use load detect */ + if (intel_get_load_detect_pipe(connector, NULL, &tmp, &ctx)) { + if (intel_crt_detect_ddc(connector)) + status = connector_status_connected; + else if (INTEL_INFO(dev)->gen < 4) + status = intel_crt_load_detect(crt); + intel_release_load_detect_pipe(connector, &tmp, &ctx); + } else if (status == connector_status_connected) status = connector_status_unknown; - intel_release_load_detect_pipe(connector, &tmp, &ctx); - } else - status = connector_status_unknown; - drm_modeset_drop_locks(&ctx); - drm_modeset_acquire_fini(&ctx); + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); + } out: intel_display_power_put(dev_priv, power_domain); diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index 8b9d325..e3c0fed 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -1313,44 +1313,37 @@ static void intel_tv_find_better_format(struct drm_connector *connector) static enum drm_connector_status intel_tv_detect(struct drm_connector *connector, bool force) { - struct drm_display_mode mode; struct intel_tv *intel_tv = intel_attached_tv(connector); - enum drm_connector_status status; - int type; + enum drm_connector_status status = connector->status; DRM_DEBUG_KMS("[CONNECTOR:%d:%s] force=%d\n", connector->base.id, connector->name, force); - - mode = reported_modes[0]; - if (force) { + struct drm_display_mode mode = reported_modes[0]; struct intel_load_detect_pipe tmp; struct drm_modeset_acquire_ctx ctx; drm_modeset_acquire_init(&ctx, 0); if (intel_get_load_detect_pipe(connector, &mode, &tmp, &ctx)) { - type = intel_tv_detect_type(intel_tv, connector); + int type = intel_tv_detect_type(intel_tv, connector); intel_release_load_detect_pipe(connector, &tmp, &ctx); status = type < 0 ? connector_status_disconnected : connector_status_connected; - } else + intel_tv->type = type; + } else if (status == connector_status_connected) status = connector_status_unknown; drm_modeset_drop_locks(&ctx); drm_modeset_acquire_fini(&ctx); - } else - return connector->status; - if (status != connector_status_connected) - return status; - - intel_tv->type = type; - intel_tv_find_better_format(connector); + if (status == connector_status_connected) + intel_tv_find_better_format(connector); + } - return connector_status_connected; + return status; } static const struct input_res {