From patchwork Fri Jun 23 13:31:44 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Vetter X-Patchwork-Id: 9806579 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 7483960349 for ; Fri, 23 Jun 2017 13:31:57 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 639FD28581 for ; Fri, 23 Jun 2017 13:31:57 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 588202867D; Fri, 23 Jun 2017 13:31:57 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.1 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED, T_DKIM_INVALID autolearn=unavailable version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id DC70728581 for ; Fri, 23 Jun 2017 13:31:56 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 945506E118; Fri, 23 Jun 2017 13:31:54 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-lf0-x244.google.com (mail-lf0-x244.google.com [IPv6:2a00:1450:4010:c07::244]) by gabe.freedesktop.org (Postfix) with ESMTPS id 0AF9D6E776 for ; Fri, 23 Jun 2017 13:31:53 +0000 (UTC) Received: by mail-lf0-x244.google.com with SMTP id g21so1147625lfk.1 for ; Fri, 23 Jun 2017 06:31:52 -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:in-reply-to:references; bh=9NelkeJ/V1ytu5KWaOqbjRX9jJGUaYT5sB518BJkUsQ=; b=dKgOC5aydML5YIf2T4XqTwdFhGwtp7LqU/rFk+OPjEpEk048tQLuaIYKb6LfwPSh36 XnJCIvBrJ6DXJtf5/AkRfsCLXmHX0DKLFw2Rh4FdvGLiwPDW4xCgArlwUuR17Kd4Atb3 ZfgjSfgCRNbT/LLlwvFJj4ZTADObzzdowp+s0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=9NelkeJ/V1ytu5KWaOqbjRX9jJGUaYT5sB518BJkUsQ=; b=rfIhC8ty1qSIMSVD0HZlO74y0rI8SQLXhzAjC1wJXIr1Q2D1wwH0DFSYGtGEg9f13u 6QZsW1KUz7kmwATFQKvOT2Zl2h+AkPhYYFLB8lBYhRu2vGDthodSFc8OgwIHtJiXom3b q7muILF5QMnmWFOTlVtn9eGjR0DEg0Tb9N4wMB46aXNiJMW8jPe7xdjYp1KuJB4QCyRg ArWSfzVORS8BnMww9ClMjtNVK963jUh9akcWi2PAPI8GUms4ZmNJRPM7aatUnPs4UjxY xck+r2svoFjk51KyS+imLGtFc8JB0qzJ5SzxGggmF13MB19snPb7nEsbiY9TZ/qhCP+V q3Ag== X-Gm-Message-State: AKS2vOxyMYDW1y6m/4sq7G8lBPc615WZD/5vMB1MPKZ4ZHfwzwfFCYzb qRRcg5iX5D/LI+D1OlU= X-Received: by 10.80.152.22 with SMTP id g22mr6258032edb.38.1498224711041; Fri, 23 Jun 2017 06:31:51 -0700 (PDT) Received: from phenom.ffwll.local ([2a02:168:5640:0:960b:2678:e223:c1c6]) by smtp.gmail.com with ESMTPSA id l25sm2799834eda.38.2017.06.23.06.31.49 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 23 Jun 2017 06:31:49 -0700 (PDT) From: Daniel Vetter To: DRI Development Subject: [PATCH] drm/fb-helper: Support deferred setup Date: Fri, 23 Jun 2017 15:31:44 +0200 Message-Id: <20170623133144.32379-1-daniel.vetter@ffwll.ch> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170621182815.14602-11-daniel.vetter@ffwll.ch> References: <20170621182815.14602-11-daniel.vetter@ffwll.ch> Cc: Intel Graphics Development , Thierry Reding , Daniel Vetter X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Thierry Reding FB helper code falls back to a 1024x768 mode if no outputs are connected or don't report back any modes upon initialization. This can be annoying because outputs that are added to FB helper later on can't be used with FB helper if they don't support a matching mode. The fallback is in place because VGA connectors can happen to report an unknown connection status even when they are in fact connected. Some drivers have custom solutions in place to defer FB helper setup until at least one output is connected. But the logic behind these solutions is always the same and there is nothing driver-specific about it, so a better alterative is to fix the FB helper core and add support for all drivers automatically. This patch adds support for deferred FB helper setup. It checks all the connectors for their connection status, and if all of them report to be disconnected marks the FB helper as needing deferred setup. Whet setup is deferred, the FB helper core will automatically retry setup after a hotplug event, and it will keep trying until it succeeds. v2: Rebase onto my entirely reworked fbdev helper locking. One big difference is that this version again drops&reacquires the fbdev lock (which is now fb_helper->lock, but before this patch series it was mode_config->mutex), because register_framebuffer must be able to recurse back into fbdev helper code for the initial screen setup. v3: __drm_fb_helper_initial_config must hold fb_helper->lock upon return, I've fumbled that in the deferred setup case (Liviu). Cc: Liviu Dudau Cc: John Stultz Cc: Thierry Reding (v1) Tested-by: John Stultz Signed-off-by: Thierry Reding (v1) Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_fb_helper.c | 110 ++++++++++++++++++++++++++++++---------- include/drm/drm_fb_helper.h | 23 +++++++++ 2 files changed, 106 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index e3d033df068f..834c7e7d7efc 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -521,6 +521,9 @@ int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper) if (!drm_fbdev_emulation) return -ENODEV; + if (READ_ONCE(fb_helper->deferred_setup)) + return 0; + mutex_lock(&fb_helper->lock); ret = restore_fbdev_mode(fb_helper); @@ -1693,6 +1696,23 @@ int drm_fb_helper_pan_display(struct fb_var_screeninfo *var, } EXPORT_SYMBOL(drm_fb_helper_pan_display); +static bool drm_fb_helper_maybe_connected(struct drm_fb_helper *helper) +{ + bool connected = false; + unsigned int i; + + for (i = 0; i < helper->connector_count; i++) { + struct drm_fb_helper_connector *fb = helper->connector_info[i]; + + if (fb->connector->status != connector_status_disconnected) { + connected = true; + break; + } + } + + return connected; +} + /* * Allocates the backing storage and sets up the fbdev info structure through * the ->fb_probe callback and then registers the fbdev and sets up the panic @@ -2352,8 +2372,6 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, int i; DRM_DEBUG_KMS("\n"); - if (drm_fb_helper_probe_connector_modes(fb_helper, width, height) == 0) - DRM_DEBUG_KMS("No connectors reported connected with modes\n"); /* prevent concurrent modification of connector_count by hotplug */ lockdep_assert_held(&fb_helper->lock); @@ -2431,6 +2449,60 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, kfree(enabled); } +/* Note: Drops&reacquires fb_helper->lock */ +static int __drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, + int bpp_sel) +{ + struct drm_device *dev = fb_helper->dev; + struct fb_info *info; + unsigned int width, height; + int ret; + + width = dev->mode_config.max_width; + height = dev->mode_config.max_height; + + if (drm_fb_helper_probe_connector_modes(fb_helper, width, height) == 0) + DRM_DEBUG_KMS("No connectors reported connected with modes\n"); + + /* + * If everything's disconnected, there's no use in attempting to set + * up fbdev. + */ + if (!drm_fb_helper_maybe_connected(fb_helper)) { + DRM_INFO("No outputs connected, deferring setup\n"); + fb_helper->preferred_bpp = bpp_sel; + fb_helper->deferred_setup = true; + return 0; + } + + drm_setup_crtcs(fb_helper, width, height); + ret = drm_fb_helper_single_fb_probe(fb_helper, bpp_sel); + if (ret) { + mutex_unlock(&fb_helper->lock); + return ret; + } + + fb_helper->deferred_setup = false; + mutex_unlock(&fb_helper->lock); + + info = fb_helper->fbdev; + info->var.pixclock = 0; + ret = register_framebuffer(info); + if (ret < 0) + return ret; + + dev_info(dev->dev, "fb%d: %s frame buffer device\n", + info->node, info->fix.id); + + mutex_lock(&kernel_fb_helper_lock); + if (list_empty(&kernel_fb_helper_list)) + register_sysrq_key('v', &sysrq_drm_fb_helper_restore_op); + + list_add(&fb_helper->kernel_fb_list, &kernel_fb_helper_list); + + return 0; +} + /** * drm_fb_helper_initial_config - setup a sane initial connector configuration * @fb_helper: fb_helper device struct @@ -2475,39 +2547,16 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, */ int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel) { - struct drm_device *dev = fb_helper->dev; - struct fb_info *info; int ret; if (!drm_fbdev_emulation) return 0; mutex_lock(&fb_helper->lock); - drm_setup_crtcs(fb_helper, - dev->mode_config.max_width, - dev->mode_config.max_height); - ret = drm_fb_helper_single_fb_probe(fb_helper, bpp_sel); - mutex_unlock(&fb_helper->lock); - if (ret) - return ret; - - info = fb_helper->fbdev; - info->var.pixclock = 0; - ret = register_framebuffer(info); - if (ret < 0) - return ret; - - dev_info(dev->dev, "fb%d: %s frame buffer device\n", - info->node, info->fix.id); - - mutex_lock(&kernel_fb_helper_lock); - if (list_empty(&kernel_fb_helper_list)) - register_sysrq_key('v', &sysrq_drm_fb_helper_restore_op); - - list_add(&fb_helper->kernel_fb_list, &kernel_fb_helper_list); + ret = __drm_fb_helper_initial_config(fb_helper, bpp_sel); mutex_unlock(&kernel_fb_helper_lock); - return 0; + return ret; } EXPORT_SYMBOL(drm_fb_helper_initial_config); @@ -2540,6 +2589,13 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper) return 0; mutex_lock(&fb_helper->lock); + if (fb_helper->deferred_setup) { + err = __drm_fb_helper_initial_config(fb_helper, + fb_helper->preferred_bpp); + mutex_unlock(&fb_helper->lock); + return err; + } + if (!fb_helper->fb || !drm_fb_helper_is_bound(fb_helper)) { fb_helper->delayed_hotplug = true; mutex_unlock(&fb_helper->lock); diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index ea170b96e88d..a5ea6ffdfecc 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -232,6 +232,29 @@ struct drm_fb_helper { * needs to be reprobe when fbdev is in control again. */ bool delayed_hotplug; + + /** + * @deferred_setup: + * + * If no outputs are connected (disconnected or unknown) the FB helper + * code will defer setup until at least one of the outputs shows up. + * This field keeps track of the status so that setup can be retried + * at every hotplug event until it succeeds eventually. + * + * Protected by @lock. + */ + bool deferred_setup; + + /** + * @preferred_bpp: + * + * Temporary storage for the driver's preferred BPP setting passed to + * FB helper initialization. This needs to be tracked so that deferred + * FB helper setup can pass this on. + * + * See also: @deferred_setup + */ + int preferred_bpp; }; /**