From patchwork Tue Mar 26 17:55:36 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Noralf_Tr=C3=B8nnes?= X-Patchwork-Id: 10871827 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 9EA72922 for ; Tue, 26 Mar 2019 17:56:33 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8B2B628D54 for ; Tue, 26 Mar 2019 17:56:33 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7E68A28D6A; Tue, 26 Mar 2019 17:56:33 +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=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham 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 881E428D54 for ; Tue, 26 Mar 2019 17:56:32 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 142EC6E06B; Tue, 26 Mar 2019 17:56:15 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from smtp.domeneshop.no (smtp.domeneshop.no [IPv6:2a01:5b40:0:3005::1]) by gabe.freedesktop.org (Postfix) with ESMTPS id 857156E06C; Tue, 26 Mar 2019 17:56:08 +0000 (UTC) Received: from 211.81-166-168.customer.lyse.net ([81.166.168.211]:46322 helo=localhost.localdomain) by smtp.domeneshop.no with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.84_2) (envelope-from ) id 1h8qIw-0006Mj-3L; Tue, 26 Mar 2019 18:56:06 +0100 From: =?utf-8?q?Noralf_Tr=C3=B8nnes?= To: dri-devel@lists.freedesktop.org Date: Tue, 26 Mar 2019 18:55:36 +0100 Message-Id: <20190326175546.18126-7-noralf@tronnes.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190326175546.18126-1-noralf@tronnes.org> References: <20190326175546.18126-1-noralf@tronnes.org> MIME-Version: 1.0 X-Mailman-Original-DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=tronnes.org; s=ds201810; h=Content-Transfer-Encoding:Content-Type:MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=z72ufDsSc3B/+8cqKZfzG4DUMyWjMVJ8WvjRyAX3ZjI=; b=dHByBq5i/jobauWfpXFC78Uz1R83e2u46i0NHKSS73m/t2eEhhZCqmfEFkChNjg9lTwbCOrne/iQg1L8S853Dk6MEboJOIjDL/vnWBFB3BAewfK8WKj7SUgoLALIWWyuY9suT7yMgUIGQglEuwU8+4UKZPMOhxHdd4nrs3LJ5wI/dVyWuXIqrIaP3Nj1sEklrbZsUHC8QixsPGBjRisbeOgedWJxFeOOHBOkAIurCE+YPPM05Z5ee6MhIHehF21f9Y+WmI5MZMKQgApbVHdeE7sw1VVLDJcE3NTFERSsYNm53QVzNV5/4WjQJy8hXbc/7iFl34XNTXJA67NnzHqU+Q==; Subject: [Intel-gfx] [PATCH 06/16] drm/i915/fbdev: Move intel_fb_initial_config() to fbdev helper X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Daniel Vetter , intel-gfx@lists.freedesktop.org, =?utf-8?q?Noralf_Tr=C3=B8nnes?= , mstaudt@suse.de Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP It is generic code and having it in the helper will let other drivers benefit from it. One change was necessary assuming this to be true: INTEL_INFO(dev_priv)->num_pipes == dev->mode_config.num_crtc Suggested-by: Daniel Vetter Cc: Jani Nikula Cc: Joonas Lahtinen Cc: Rodrigo Vivi Cc: intel-gfx@lists.freedesktop.org Signed-off-by: Noralf Trønnes Reviewed-by: Jani Nikula Acked-by: Jani Nikula --- drivers/gpu/drm/drm_fb_helper.c | 194 ++++++++++++++++++++++++- drivers/gpu/drm/i915/intel_fbdev.c | 218 ----------------------------- include/drm/drm_fb_helper.h | 23 --- 3 files changed, 190 insertions(+), 245 deletions(-) diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 36310901e935..634f4dcf0c41 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -2545,6 +2545,194 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper, return best_score; } +static struct drm_fb_helper_crtc * +drm_fb_helper_crtc(struct drm_fb_helper *fb_helper, struct drm_crtc *crtc) +{ + int i; + + for (i = 0; i < fb_helper->crtc_count; i++) + if (fb_helper->crtc_info[i].mode_set.crtc == crtc) + return &fb_helper->crtc_info[i]; + + return NULL; +} + +/* Try to read the BIOS display configuration and use it for the initial config */ +static bool drm_fb_helper_firmware_config(struct drm_fb_helper *fb_helper, + struct drm_fb_helper_crtc **crtcs, + struct drm_display_mode **modes, + struct drm_fb_offset *offsets, + bool *enabled, int width, int height) +{ + struct drm_device *dev = fb_helper->dev; + unsigned int count = min(fb_helper->connector_count, BITS_PER_LONG); + unsigned long conn_configured, conn_seq; + int i, j; + bool *save_enabled; + bool fallback = true, ret = true; + int num_connectors_enabled = 0; + int num_connectors_detected = 0; + struct drm_modeset_acquire_ctx ctx; + + save_enabled = kcalloc(count, sizeof(bool), GFP_KERNEL); + if (!save_enabled) + return false; + + drm_modeset_acquire_init(&ctx, 0); + + while (drm_modeset_lock_all_ctx(dev, &ctx) != 0) + drm_modeset_backoff(&ctx); + + memcpy(save_enabled, enabled, count); + conn_seq = GENMASK(count - 1, 0); + conn_configured = 0; +retry: + for (i = 0; i < count; i++) { + struct drm_fb_helper_connector *fb_conn; + struct drm_connector *connector; + struct drm_encoder *encoder; + struct drm_fb_helper_crtc *new_crtc; + + fb_conn = fb_helper->connector_info[i]; + connector = fb_conn->connector; + + if (conn_configured & BIT(i)) + continue; + + /* First pass, only consider tiled connectors */ + if (conn_seq == GENMASK(count - 1, 0) && !connector->has_tile) + continue; + + if (connector->status == connector_status_connected) + num_connectors_detected++; + + if (!enabled[i]) { + DRM_DEBUG_KMS("connector %s not enabled, skipping\n", + connector->name); + conn_configured |= BIT(i); + continue; + } + + if (connector->force == DRM_FORCE_OFF) { + DRM_DEBUG_KMS("connector %s is disabled by user, skipping\n", + connector->name); + enabled[i] = false; + continue; + } + + encoder = connector->state->best_encoder; + if (!encoder || WARN_ON(!connector->state->crtc)) { + if (connector->force > DRM_FORCE_OFF) + goto bail; + + DRM_DEBUG_KMS("connector %s has no encoder or crtc, skipping\n", + connector->name); + enabled[i] = false; + conn_configured |= BIT(i); + continue; + } + + num_connectors_enabled++; + + new_crtc = drm_fb_helper_crtc(fb_helper, connector->state->crtc); + + /* + * Make sure we're not trying to drive multiple connectors + * with a single CRTC, since our cloning support may not + * match the BIOS. + */ + for (j = 0; j < count; j++) { + if (crtcs[j] == new_crtc) { + DRM_DEBUG_KMS("fallback: cloned configuration\n"); + goto bail; + } + } + + DRM_DEBUG_KMS("looking for cmdline mode on connector %s\n", + connector->name); + + /* go for command line mode first */ + modes[i] = drm_pick_cmdline_mode(fb_conn); + + /* try for preferred next */ + if (!modes[i]) { + DRM_DEBUG_KMS("looking for preferred mode on connector %s %d\n", + connector->name, connector->has_tile); + modes[i] = drm_has_preferred_mode(fb_conn, width, + height); + } + + /* No preferred mode marked by the EDID? Are there any modes? */ + if (!modes[i] && !list_empty(&connector->modes)) { + DRM_DEBUG_KMS("using first mode listed on connector %s\n", + connector->name); + modes[i] = list_first_entry(&connector->modes, + struct drm_display_mode, + head); + } + + /* last resort: use current mode */ + if (!modes[i]) { + /* + * IMPORTANT: We want to use the adjusted mode (i.e. + * after the panel fitter upscaling) as the initial + * config, not the input mode, which is what crtc->mode + * usually contains. But since our current + * code puts a mode derived from the post-pfit timings + * into crtc->mode this works out correctly. + * + * This is crtc->mode and not crtc->state->mode for the + * fastboot check to work correctly. + */ + DRM_DEBUG_KMS("looking for current mode on connector %s\n", + connector->name); + modes[i] = &connector->state->crtc->mode; + } + crtcs[i] = new_crtc; + + DRM_DEBUG_KMS("connector %s on [CRTC:%d:%s]: %dx%d%s\n", + connector->name, + connector->state->crtc->base.id, + connector->state->crtc->name, + modes[i]->hdisplay, modes[i]->vdisplay, + modes[i]->flags & DRM_MODE_FLAG_INTERLACE ? "i" : ""); + + fallback = false; + conn_configured |= BIT(i); + } + + if (conn_configured != conn_seq) { /* repeat until no more are found */ + conn_seq = conn_configured; + goto retry; + } + + /* + * If the BIOS didn't enable everything it could, fall back to have the + * same user experiencing of lighting up as much as possible like the + * fbdev helper library. + */ + if (num_connectors_enabled != num_connectors_detected && + num_connectors_enabled < dev->mode_config.num_crtc) { + DRM_DEBUG_KMS("fallback: Not all outputs enabled\n"); + DRM_DEBUG_KMS("Enabled: %i, detected: %i\n", num_connectors_enabled, + num_connectors_detected); + fallback = true; + } + + if (fallback) { +bail: + DRM_DEBUG_KMS("Not using firmware configuration\n"); + memcpy(enabled, save_enabled, count); + ret = false; + } + + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); + + kfree(save_enabled); + return ret; +} + static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, u32 width, u32 height) { @@ -2577,10 +2765,8 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, DRM_DEBUG_KMS("No connectors reported connected with modes\n"); drm_enable_connectors(fb_helper, enabled); - if (!(fb_helper->funcs->initial_config && - fb_helper->funcs->initial_config(fb_helper, crtcs, modes, - offsets, - enabled, width, height))) { + if (!drm_fb_helper_firmware_config(fb_helper, crtcs, modes, offsets, + enabled, width, height)) { memset(modes, 0, fb_helper->connector_count*sizeof(modes[0])); memset(crtcs, 0, fb_helper->connector_count*sizeof(crtcs[0])); memset(offsets, 0, fb_helper->connector_count*sizeof(offsets[0])); diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index e8f694b57b8a..20e91600cf71 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -292,225 +292,7 @@ static int intelfb_create(struct drm_fb_helper *helper, return ret; } -static struct drm_fb_helper_crtc * -intel_fb_helper_crtc(struct drm_fb_helper *fb_helper, struct drm_crtc *crtc) -{ - int i; - - for (i = 0; i < fb_helper->crtc_count; i++) - if (fb_helper->crtc_info[i].mode_set.crtc == crtc) - return &fb_helper->crtc_info[i]; - - return NULL; -} - -/* - * Try to read the BIOS display configuration and use it for the initial - * fb configuration. - * - * The BIOS or boot loader will generally create an initial display - * configuration for us that includes some set of active pipes and displays. - * This routine tries to figure out which pipes and connectors are active - * and stuffs them into the crtcs and modes array given to us by the - * drm_fb_helper code. - * - * The overall sequence is: - * intel_fbdev_init - from driver load - * intel_fbdev_init_bios - initialize the intel_fbdev using BIOS data - * drm_fb_helper_init - build fb helper structs - * drm_fb_helper_single_add_all_connectors - more fb helper structs - * intel_fbdev_initial_config - apply the config - * drm_fb_helper_initial_config - call ->probe then register_framebuffer() - * drm_setup_crtcs - build crtc config for fbdev - * intel_fb_initial_config - find active connectors etc - * drm_fb_helper_single_fb_probe - set up fbdev - * intelfb_create - re-use or alloc fb, build out fbdev structs - * - * Note that we don't make special consideration whether we could actually - * switch to the selected modes without a full modeset. E.g. when the display - * is in VGA mode we need to recalculate watermarks and set a new high-res - * framebuffer anyway. - */ -static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper, - struct drm_fb_helper_crtc **crtcs, - struct drm_display_mode **modes, - struct drm_fb_offset *offsets, - bool *enabled, int width, int height) -{ - struct drm_i915_private *dev_priv = to_i915(fb_helper->dev); - unsigned int count = min(fb_helper->connector_count, BITS_PER_LONG); - unsigned long conn_configured, conn_seq; - int i, j; - bool *save_enabled; - bool fallback = true, ret = true; - int num_connectors_enabled = 0; - int num_connectors_detected = 0; - struct drm_modeset_acquire_ctx ctx; - - save_enabled = kcalloc(count, sizeof(bool), GFP_KERNEL); - if (!save_enabled) - return false; - - drm_modeset_acquire_init(&ctx, 0); - - while (drm_modeset_lock_all_ctx(fb_helper->dev, &ctx) != 0) - drm_modeset_backoff(&ctx); - - memcpy(save_enabled, enabled, count); - conn_seq = GENMASK(count - 1, 0); - conn_configured = 0; -retry: - for (i = 0; i < count; i++) { - struct drm_fb_helper_connector *fb_conn; - struct drm_connector *connector; - struct drm_encoder *encoder; - struct drm_fb_helper_crtc *new_crtc; - - fb_conn = fb_helper->connector_info[i]; - connector = fb_conn->connector; - - if (conn_configured & BIT(i)) - continue; - - /* First pass, only consider tiled connectors */ - if (conn_seq == GENMASK(count - 1, 0) && !connector->has_tile) - continue; - - if (connector->status == connector_status_connected) - num_connectors_detected++; - - if (!enabled[i]) { - DRM_DEBUG_KMS("connector %s not enabled, skipping\n", - connector->name); - conn_configured |= BIT(i); - continue; - } - - if (connector->force == DRM_FORCE_OFF) { - DRM_DEBUG_KMS("connector %s is disabled by user, skipping\n", - connector->name); - enabled[i] = false; - continue; - } - - encoder = connector->state->best_encoder; - if (!encoder || WARN_ON(!connector->state->crtc)) { - if (connector->force > DRM_FORCE_OFF) - goto bail; - - DRM_DEBUG_KMS("connector %s has no encoder or crtc, skipping\n", - connector->name); - enabled[i] = false; - conn_configured |= BIT(i); - continue; - } - - num_connectors_enabled++; - - new_crtc = intel_fb_helper_crtc(fb_helper, - connector->state->crtc); - - /* - * Make sure we're not trying to drive multiple connectors - * with a single CRTC, since our cloning support may not - * match the BIOS. - */ - for (j = 0; j < count; j++) { - if (crtcs[j] == new_crtc) { - DRM_DEBUG_KMS("fallback: cloned configuration\n"); - goto bail; - } - } - - DRM_DEBUG_KMS("looking for cmdline mode on connector %s\n", - connector->name); - - /* go for command line mode first */ - modes[i] = drm_pick_cmdline_mode(fb_conn); - - /* try for preferred next */ - if (!modes[i]) { - DRM_DEBUG_KMS("looking for preferred mode on connector %s %d\n", - connector->name, connector->has_tile); - modes[i] = drm_has_preferred_mode(fb_conn, width, - height); - } - - /* No preferred mode marked by the EDID? Are there any modes? */ - if (!modes[i] && !list_empty(&connector->modes)) { - DRM_DEBUG_KMS("using first mode listed on connector %s\n", - connector->name); - modes[i] = list_first_entry(&connector->modes, - struct drm_display_mode, - head); - } - - /* last resort: use current mode */ - if (!modes[i]) { - /* - * IMPORTANT: We want to use the adjusted mode (i.e. - * after the panel fitter upscaling) as the initial - * config, not the input mode, which is what crtc->mode - * usually contains. But since our current - * code puts a mode derived from the post-pfit timings - * into crtc->mode this works out correctly. - * - * This is crtc->mode and not crtc->state->mode for the - * fastboot check to work correctly. crtc_state->mode has - * I915_MODE_FLAG_INHERITED, which we clear to force check - * state. - */ - DRM_DEBUG_KMS("looking for current mode on connector %s\n", - connector->name); - modes[i] = &connector->state->crtc->mode; - } - crtcs[i] = new_crtc; - - DRM_DEBUG_KMS("connector %s on [CRTC:%d:%s]: %dx%d%s\n", - connector->name, - connector->state->crtc->base.id, - connector->state->crtc->name, - modes[i]->hdisplay, modes[i]->vdisplay, - modes[i]->flags & DRM_MODE_FLAG_INTERLACE ? "i" :""); - - fallback = false; - conn_configured |= BIT(i); - } - - if (conn_configured != conn_seq) { /* repeat until no more are found */ - conn_seq = conn_configured; - goto retry; - } - - /* - * If the BIOS didn't enable everything it could, fall back to have the - * same user experiencing of lighting up as much as possible like the - * fbdev helper library. - */ - if (num_connectors_enabled != num_connectors_detected && - num_connectors_enabled < INTEL_INFO(dev_priv)->num_pipes) { - DRM_DEBUG_KMS("fallback: Not all outputs enabled\n"); - DRM_DEBUG_KMS("Enabled: %i, detected: %i\n", num_connectors_enabled, - num_connectors_detected); - fallback = true; - } - - if (fallback) { -bail: - DRM_DEBUG_KMS("Not using firmware configuration\n"); - memcpy(enabled, save_enabled, count); - ret = false; - } - - drm_modeset_drop_locks(&ctx); - drm_modeset_acquire_fini(&ctx); - - kfree(save_enabled); - return ret; -} - static const struct drm_fb_helper_funcs intel_fb_helper_funcs = { - .initial_config = intel_fb_initial_config, .fb_probe = intelfb_create, }; diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index 7a095964f6b2..bca4b34dc93b 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -100,29 +100,6 @@ struct drm_fb_helper_funcs { */ int (*fb_probe)(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes); - - /** - * @initial_config: - * - * Driver callback to setup an initial fbdev display configuration. - * Drivers can use this callback to tell the fbdev emulation what the - * preferred initial configuration is. This is useful to implement - * smooth booting where the fbdev (and subsequently all userspace) never - * changes the mode, but always inherits the existing configuration. - * - * This callback is optional. - * - * RETURNS: - * - * The driver should return true if a suitable initial configuration has - * been filled out and false when the fbdev helper should fall back to - * the default probing logic. - */ - bool (*initial_config)(struct drm_fb_helper *fb_helper, - struct drm_fb_helper_crtc **crtcs, - struct drm_display_mode **modes, - struct drm_fb_offset *offsets, - bool *enabled, int width, int height); }; struct drm_fb_helper_connector {