From patchwork Tue Oct 23 18:23:33 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Vetter X-Patchwork-Id: 1632211 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by patchwork2.kernel.org (Postfix) with ESMTP id 53764DF283 for ; Tue, 23 Oct 2012 19:33:50 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 4780F9F75B for ; Tue, 23 Oct 2012 12:33:50 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-wi0-f171.google.com (mail-wi0-f171.google.com [209.85.212.171]) by gabe.freedesktop.org (Postfix) with ESMTP id 831B29F6FE for ; Tue, 23 Oct 2012 12:31:59 -0700 (PDT) Received: by mail-wi0-f171.google.com with SMTP id hj13so3080966wib.12 for ; Tue, 23 Oct 2012 12:31:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ffwll.ch; s=google; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; bh=kCljVNWQQaauH6b9s+5I4oK064gSP8gCx/W7GUFW3aQ=; b=IU99Iwilx9Bvol3ahseUTIhWraRfRLg91NQng00MiK9Pc3AtBASs1KjZgsBSN+8hhU MejYa537hyKgMRJM93wmf5AqnwF/aEDocNOW8tSF8tYrJdvgISfA8jxLwuKlHc0uYeBz kJkW5xcSbizLfHD9kEI83U2tcWJ3h3jWQk5rU= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references :x-gm-message-state; bh=kCljVNWQQaauH6b9s+5I4oK064gSP8gCx/W7GUFW3aQ=; b=XC/N3FGluAW1bqaO9o7rQIGOUE/Uwx+xVdOfNQSh4xGSoxURQh5BDq4w/0q621x2Ad Rh5L0wdz4MH2luw7uFpeqf4SeMFoEendCAD9nxssl+iutwhtpkkQQlvf8sStMMVi3TP1 mjMqVv9vdtuT39DPfUYN1xJ0FI2zfgqQAQ9w2giwHqgGfb6FHwWuRmxuZEIr0TR6peFl fsuG0iajXZtAA/Ezvj3/nfwOXHqYSmChucSthsKw/CxZj+xw5Y0JdLzovU/i45VR77y5 d9mItMBiGcXxXXOx/iRdctwiM3G7c7xAiwANKm7UbfzlIE0BrTjqF03z7Wxm/ed0ZyWn b4Lw== Received: by 10.180.89.234 with SMTP id br10mr334813wib.2.1351020718470; Tue, 23 Oct 2012 12:31:58 -0700 (PDT) Received: from wespe.ffwll.local (178-83-130-250.dynamic.hispeed.ch. [178.83.130.250]) by mx.google.com with ESMTPS id di7sm312800wib.11.2012.10.23.12.31.57 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 23 Oct 2012 12:31:57 -0700 (PDT) From: Daniel Vetter To: DRI Development Subject: [PATCH 2/7] drm: handle HPD and polled connectors separately Date: Tue, 23 Oct 2012 20:23:33 +0200 Message-Id: <1351016618-2752-3-git-send-email-daniel.vetter@ffwll.ch> X-Mailer: git-send-email 1.7.11.7 In-Reply-To: <1351016618-2752-1-git-send-email-daniel.vetter@ffwll.ch> References: <1351016618-2752-1-git-send-email-daniel.vetter@ffwll.ch> X-Gm-Message-State: ALoCoQm6b8GM2LgeeuTYImaku7IlT7ptBbLXTKD+hzU6jb4vxd2bFrS4K4JEFROOJYlg36W5gYZt Cc: Daniel Vetter X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org Errors-To: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org Instead of reusing the polling code for hpd handling, split them up. This has a few consequences: - Don't touch HPD capable connectors in the poll loop. - Only touch HPD capable connectors in drm_helper_hpd_irq_event. - We could run the HPD handling directly (because all callers already use their own work item), but for easier bisect that happens in it's own patch. The ultimate goal is that drivers grow some smarts about which connectors have received a hotplug event and only call the detect code of that connector. But that's a second step. v2: s/hdp/hpd/, noticed by Adam Jackson. I can't type. v3: Split out the work item removal as requested by Dave Airlie. This results in a temporary mode_config.hpd_irq_work item to keep things the same. v4: In the hpd_irq_event handler don't bail out if other bits than HPD are set. This is useful where e.g. hpd is unreliably, but mostly works. Drivers can then set both HPD and POLL flags, and users get the best of both worlds: Quick hotplug feedback if the hpd works, but still reliable detection with the polling. The poll loop already works the same, and doesn't bail if HPD is set. Signed-Off-by: Daniel Vetter --- drivers/gpu/drm/drm_crtc_helper.c | 51 ++++++++++++++++++++++++++++++++------- include/drm/drm_crtc.h | 1 + 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index accfd3b..7342f61 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -942,9 +942,9 @@ static void output_poll_execute(struct work_struct *work) mutex_lock(&dev->mode_config.mutex); list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - /* if this is HPD or polled don't check it - - TV out for instance */ - if (!connector->polled) + /* Ignore HPD capable connectors and connectors where we don't + * want any hotplug detection at all for polling. */ + if (!connector->polled || connector->polled == DRM_CONNECTOR_POLL_HPD) continue; else if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT)) @@ -954,8 +954,7 @@ static void output_poll_execute(struct work_struct *work) /* if we are connected and don't want to poll for disconnect skip it */ if (old_status == connector_status_connected && - !(connector->polled & DRM_CONNECTOR_POLL_DISCONNECT) && - !(connector->polled & DRM_CONNECTOR_POLL_HPD)) + !(connector->polled & DRM_CONNECTOR_POLL_DISCONNECT)) continue; connector->status = connector->funcs->detect(connector, false); @@ -1002,9 +1001,12 @@ void drm_kms_helper_poll_enable(struct drm_device *dev) } EXPORT_SYMBOL(drm_kms_helper_poll_enable); +static void hpd_irq_event_execute(struct work_struct *work); + void drm_kms_helper_poll_init(struct drm_device *dev) { INIT_DELAYED_WORK(&dev->mode_config.output_poll_work, output_poll_execute); + INIT_DELAYED_WORK(&dev->mode_config.hpd_irq_work, hpd_irq_event_execute); dev->mode_config.poll_enabled = true; drm_kms_helper_poll_enable(dev); @@ -1017,14 +1019,45 @@ void drm_kms_helper_poll_fini(struct drm_device *dev) } EXPORT_SYMBOL(drm_kms_helper_poll_fini); -void drm_helper_hpd_irq_event(struct drm_device *dev) +static void hpd_irq_event_execute(struct work_struct *work) { + struct delayed_work *delayed_work = to_delayed_work(work); + struct drm_device *dev = container_of(delayed_work, struct drm_device, mode_config.hpd_irq_work); + struct drm_connector *connector; + enum drm_connector_status old_status; + bool changed = false; + if (!dev->mode_config.poll_enabled) return; - /* kill timer and schedule immediate execution, this doesn't block */ - cancel_delayed_work(&dev->mode_config.output_poll_work); + mutex_lock(&dev->mode_config.mutex); + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + + /* Only handle HPD capable connectors. */ + if (!(connector->polled & DRM_CONNECTOR_POLL_HPD)) + continue; + + old_status = connector->status; + + connector->status = connector->funcs->detect(connector, false); + DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %d to %d\n", + connector->base.id, + drm_get_connector_name(connector), + old_status, connector->status); + if (old_status != connector->status) + changed = true; + } + + mutex_unlock(&dev->mode_config.mutex); + + if (changed) + drm_kms_helper_hotplug_event(dev); +} + +void drm_helper_hpd_irq_event(struct drm_device *dev) +{ + cancel_delayed_work(&dev->mode_config.hpd_irq_work); if (drm_kms_helper_poll) - schedule_delayed_work(&dev->mode_config.output_poll_work, 0); + schedule_delayed_work(&dev->mode_config.hpd_irq_work, 0); } EXPORT_SYMBOL(drm_helper_hpd_irq_event); diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 3fa18b7..1052348 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -793,6 +793,7 @@ struct drm_mode_config { /* output poll support */ bool poll_enabled; struct delayed_work output_poll_work; + struct delayed_work hpd_irq_work; /* pointers to standard properties */ struct list_head property_blob_list;